numba-cuda 0.21.1__cp313-cp313-win_amd64.whl → 0.23.0__cp313-cp313-win_amd64.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 (78) hide show
  1. numba_cuda/VERSION +1 -1
  2. numba_cuda/numba/cuda/api.py +4 -1
  3. numba_cuda/numba/cuda/cext/_dispatcher.cp313-win_amd64.pyd +0 -0
  4. numba_cuda/numba/cuda/cext/_dispatcher.cpp +0 -38
  5. numba_cuda/numba/cuda/cext/_helperlib.cp313-win_amd64.pyd +0 -0
  6. numba_cuda/numba/cuda/cext/_typeconv.cp313-win_amd64.pyd +0 -0
  7. numba_cuda/numba/cuda/cext/_typeof.cpp +0 -111
  8. numba_cuda/numba/cuda/cext/mviewbuf.cp313-win_amd64.pyd +0 -0
  9. numba_cuda/numba/cuda/codegen.py +42 -10
  10. numba_cuda/numba/cuda/compiler.py +10 -4
  11. numba_cuda/numba/cuda/core/analysis.py +29 -21
  12. numba_cuda/numba/cuda/core/annotations/type_annotations.py +4 -4
  13. numba_cuda/numba/cuda/core/base.py +6 -1
  14. numba_cuda/numba/cuda/core/consts.py +1 -1
  15. numba_cuda/numba/cuda/core/cuda_errors.py +917 -0
  16. numba_cuda/numba/cuda/core/errors.py +4 -912
  17. numba_cuda/numba/cuda/core/inline_closurecall.py +71 -57
  18. numba_cuda/numba/cuda/core/interpreter.py +79 -64
  19. numba_cuda/numba/cuda/core/ir.py +191 -119
  20. numba_cuda/numba/cuda/core/ir_utils.py +142 -112
  21. numba_cuda/numba/cuda/core/postproc.py +8 -8
  22. numba_cuda/numba/cuda/core/rewrites/ir_print.py +6 -3
  23. numba_cuda/numba/cuda/core/rewrites/static_getitem.py +5 -5
  24. numba_cuda/numba/cuda/core/rewrites/static_raise.py +3 -3
  25. numba_cuda/numba/cuda/core/ssa.py +3 -3
  26. numba_cuda/numba/cuda/core/transforms.py +25 -10
  27. numba_cuda/numba/cuda/core/typed_passes.py +9 -9
  28. numba_cuda/numba/cuda/core/typeinfer.py +39 -24
  29. numba_cuda/numba/cuda/core/untyped_passes.py +71 -55
  30. numba_cuda/numba/cuda/cudadecl.py +0 -13
  31. numba_cuda/numba/cuda/cudadrv/devicearray.py +6 -5
  32. numba_cuda/numba/cuda/cudadrv/driver.py +132 -511
  33. numba_cuda/numba/cuda/cudadrv/dummyarray.py +4 -0
  34. numba_cuda/numba/cuda/cudadrv/nvrtc.py +16 -0
  35. numba_cuda/numba/cuda/cudaimpl.py +0 -12
  36. numba_cuda/numba/cuda/debuginfo.py +104 -10
  37. numba_cuda/numba/cuda/descriptor.py +1 -1
  38. numba_cuda/numba/cuda/device_init.py +4 -7
  39. numba_cuda/numba/cuda/dispatcher.py +36 -32
  40. numba_cuda/numba/cuda/intrinsics.py +150 -1
  41. numba_cuda/numba/cuda/lowering.py +64 -29
  42. numba_cuda/numba/cuda/memory_management/nrt.py +10 -14
  43. numba_cuda/numba/cuda/np/arrayobj.py +54 -0
  44. numba_cuda/numba/cuda/np/numpy_support.py +26 -0
  45. numba_cuda/numba/cuda/printimpl.py +20 -0
  46. numba_cuda/numba/cuda/serialize.py +10 -0
  47. numba_cuda/numba/cuda/stubs.py +0 -11
  48. numba_cuda/numba/cuda/tests/benchmarks/test_kernel_launch.py +21 -4
  49. numba_cuda/numba/cuda/tests/cudadrv/test_context_stack.py +1 -2
  50. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_driver.py +130 -48
  51. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_memory.py +6 -2
  52. numba_cuda/numba/cuda/tests/cudadrv/test_emm_plugins.py +3 -1
  53. numba_cuda/numba/cuda/tests/cudadrv/test_linker.py +5 -6
  54. numba_cuda/numba/cuda/tests/cudadrv/test_module_callbacks.py +11 -12
  55. numba_cuda/numba/cuda/tests/cudadrv/test_nvjitlink.py +27 -19
  56. numba_cuda/numba/cuda/tests/cudapy/test_caching.py +47 -0
  57. numba_cuda/numba/cuda/tests/cudapy/test_compiler.py +10 -0
  58. numba_cuda/numba/cuda/tests/cudapy/test_debuginfo.py +89 -0
  59. numba_cuda/numba/cuda/tests/cudapy/test_device_array_capture.py +243 -0
  60. numba_cuda/numba/cuda/tests/cudapy/test_dispatcher.py +3 -3
  61. numba_cuda/numba/cuda/tests/cudapy/test_numba_interop.py +35 -0
  62. numba_cuda/numba/cuda/tests/cudapy/test_print.py +51 -0
  63. numba_cuda/numba/cuda/tests/cudapy/test_warp_ops.py +116 -1
  64. numba_cuda/numba/cuda/tests/doc_examples/test_globals.py +111 -0
  65. numba_cuda/numba/cuda/tests/nocuda/test_dummyarray.py +61 -0
  66. numba_cuda/numba/cuda/tests/nrt/test_nrt.py +31 -0
  67. numba_cuda/numba/cuda/typing/context.py +3 -1
  68. numba_cuda/numba/cuda/typing/typeof.py +56 -0
  69. {numba_cuda-0.21.1.dist-info → numba_cuda-0.23.0.dist-info}/METADATA +1 -1
  70. {numba_cuda-0.21.1.dist-info → numba_cuda-0.23.0.dist-info}/RECORD +74 -74
  71. numba_cuda/numba/cuda/cext/_devicearray.cp313-win_amd64.pyd +0 -0
  72. numba_cuda/numba/cuda/cext/_devicearray.cpp +0 -159
  73. numba_cuda/numba/cuda/cext/_devicearray.h +0 -29
  74. numba_cuda/numba/cuda/intrinsic_wrapper.py +0 -41
  75. {numba_cuda-0.21.1.dist-info → numba_cuda-0.23.0.dist-info}/WHEEL +0 -0
  76. {numba_cuda-0.21.1.dist-info → numba_cuda-0.23.0.dist-info}/licenses/LICENSE +0 -0
  77. {numba_cuda-0.21.1.dist-info → numba_cuda-0.23.0.dist-info}/licenses/LICENSE.numba +0 -0
  78. {numba_cuda-0.21.1.dist-info → numba_cuda-0.23.0.dist-info}/top_level.txt +0 -0
@@ -7,8 +7,8 @@ from numba.cuda.core import ir_utils, transforms
7
7
 
8
8
  class YieldPoint(object):
9
9
  def __init__(self, block, inst):
10
- assert isinstance(block, ir.Block)
11
- assert isinstance(inst, ir.Yield)
10
+ assert isinstance(block, ir.block_types)
11
+ assert isinstance(inst, ir.yield_types)
12
12
  self.block = block
13
13
  self.inst = inst
14
14
  self.live_vars = None
@@ -111,9 +111,9 @@ class PostProcessor(object):
111
111
  assert not dct, "rerunning _populate_generator_info"
112
112
  for block in self.func_ir.blocks.values():
113
113
  for inst in block.body:
114
- if isinstance(inst, ir.Assign):
114
+ if isinstance(inst, ir.assign_types):
115
115
  yieldinst = inst.value
116
- if isinstance(yieldinst, ir.Yield):
116
+ if isinstance(yieldinst, ir.yield_types):
117
117
  index = len(dct) + 1
118
118
  yieldinst.index = index
119
119
  yp = YieldPoint(block, yieldinst)
@@ -133,18 +133,18 @@ class PostProcessor(object):
133
133
  weak_live_vars = set()
134
134
  stmts = iter(yp.block.body)
135
135
  for stmt in stmts:
136
- if isinstance(stmt, ir.Assign):
136
+ if isinstance(stmt, ir.assign_types):
137
137
  if stmt.value is yp.inst:
138
138
  break
139
139
  live_vars.add(stmt.target.name)
140
- elif isinstance(stmt, ir.Del):
140
+ elif isinstance(stmt, ir.del_types):
141
141
  live_vars.remove(stmt.value)
142
142
  else:
143
143
  assert 0, "couldn't find yield point"
144
144
  # Try to optimize out any live vars that are deleted immediately
145
145
  # after the yield point.
146
146
  for stmt in stmts:
147
- if isinstance(stmt, ir.Del):
147
+ if isinstance(stmt, ir.del_types):
148
148
  name = stmt.value
149
149
  if name in live_vars:
150
150
  live_vars.remove(name)
@@ -222,7 +222,7 @@ class PostProcessor(object):
222
222
  else:
223
223
  lastloc = stmt.loc
224
224
  # Ignore dels (assuming no user inserted deletes)
225
- if not isinstance(stmt, ir.Del):
225
+ if not isinstance(stmt, ir.del_types):
226
226
  body.append(stmt)
227
227
  # note: the reverse sort is not necessary for correctness
228
228
  # it is just to minimize changes to test for now
@@ -16,8 +16,11 @@ class RewritePrintCalls(Rewrite):
16
16
  self.prints = prints = {}
17
17
  self.block = block
18
18
  # Find all assignments with a right-hand print() call
19
- for inst in block.find_insts(ir.Assign):
20
- if isinstance(inst.value, ir.Expr) and inst.value.op == "call":
19
+ for inst in block.find_insts(ir.assign_types):
20
+ if (
21
+ isinstance(inst.value, ir.expr_types)
22
+ and inst.value.op == "call"
23
+ ):
21
24
  expr = inst.value
22
25
  try:
23
26
  callee = func_ir.infer_constant(expr.func)
@@ -68,7 +71,7 @@ class DetectConstPrintArguments(Rewrite):
68
71
  def match(self, func_ir, block, typemap, calltypes):
69
72
  self.consts = consts = {}
70
73
  self.block = block
71
- for inst in block.find_insts(ir.Print):
74
+ for inst in block.find_insts(ir.print_types):
72
75
  if inst.consts:
73
76
  # Already rewritten
74
77
  continue
@@ -37,7 +37,7 @@ class RewriteConstGetitems(Rewrite):
37
37
  new_block = self.block.copy()
38
38
  new_block.clear()
39
39
  for inst in self.block.body:
40
- if isinstance(inst, ir.Assign):
40
+ if isinstance(inst, ir.assign_types):
41
41
  expr = inst.value
42
42
  if expr in self.getitems:
43
43
  const = self.getitems[expr]
@@ -85,7 +85,7 @@ class RewriteStringLiteralGetitems(Rewrite):
85
85
  """
86
86
  new_block = ir.Block(self.block.scope, self.block.loc)
87
87
  for inst in self.block.body:
88
- if isinstance(inst, ir.Assign):
88
+ if isinstance(inst, ir.assign_types):
89
89
  expr = inst.value
90
90
  if expr in self.getitems:
91
91
  const, lit_val = self.getitems[expr]
@@ -119,7 +119,7 @@ class RewriteStringLiteralSetitems(Rewrite):
119
119
  self.setitems = setitems = {}
120
120
  self.block = block
121
121
  self.calltypes = calltypes
122
- for inst in block.find_insts(ir.SetItem):
122
+ for inst in block.find_insts(ir.setitem_types):
123
123
  index_ty = typemap[inst.index.name]
124
124
  if isinstance(index_ty, types.StringLiteral):
125
125
  setitems[inst] = (inst.index, index_ty.literal_value)
@@ -133,7 +133,7 @@ class RewriteStringLiteralSetitems(Rewrite):
133
133
  """
134
134
  new_block = ir.Block(self.block.scope, self.block.loc)
135
135
  for inst in self.block.body:
136
- if isinstance(inst, ir.SetItem):
136
+ if isinstance(inst, ir.setitem_types):
137
137
  if inst in self.setitems:
138
138
  const, lit_val = self.setitems[inst]
139
139
  new_inst = ir.StaticSetItem(
@@ -162,7 +162,7 @@ class RewriteConstSetitems(Rewrite):
162
162
  self.block = block
163
163
  # Detect all setitem statements and find which ones can be
164
164
  # rewritten
165
- for inst in block.find_insts(ir.SetItem):
165
+ for inst in block.find_insts(ir.setitem_types):
166
166
  try:
167
167
  const = func_ir.infer_constant(inst.index)
168
168
  except errors.ConstantInferenceError:
@@ -56,7 +56,7 @@ class RewriteConstRaises(Rewrite):
56
56
  self.block = block
57
57
  # Detect all raise statements and find which ones can be
58
58
  # rewritten
59
- for inst in block.find_insts((ir.Raise, ir.TryRaise)):
59
+ for inst in block.find_insts(ir.raise_types + ir.tryraise_types):
60
60
  if inst.exception is None:
61
61
  # re-reraise
62
62
  exc_type, exc_args = None, None
@@ -72,9 +72,9 @@ class RewriteConstRaises(Rewrite):
72
72
  loc = inst.exception.loc
73
73
  exc_type, exc_args = self._break_constant(const, loc)
74
74
 
75
- if isinstance(inst, ir.Raise):
75
+ if isinstance(inst, ir.raise_types):
76
76
  raises[inst] = exc_type, exc_args
77
- elif isinstance(inst, ir.TryRaise):
77
+ elif isinstance(inst, ir.tryraise_types):
78
78
  tryraises[inst] = exc_type, exc_args
79
79
  else:
80
80
  raise ValueError("unexpected: {}".format(type(inst)))
@@ -211,7 +211,7 @@ def _run_ssa_block_pass(states, blk, handler):
211
211
  _logger.debug("Running %s", handler)
212
212
  for stmt in blk.body:
213
213
  _logger.debug("on stmt: %s", stmt)
214
- if isinstance(stmt, ir.Assign):
214
+ if isinstance(stmt, ir.assign_types):
215
215
  ret = handler.on_assign(states, stmt)
216
216
  else:
217
217
  ret = handler.on_other(states, stmt)
@@ -335,7 +335,7 @@ class _FixSSAVars(_BaseHandler):
335
335
 
336
336
  def on_assign(self, states, assign):
337
337
  rhs = assign.value
338
- if isinstance(rhs, ir.Inst):
338
+ if isinstance(rhs, ir.inst_types):
339
339
  newdef = self._fix_var(
340
340
  states,
341
341
  assign,
@@ -353,7 +353,7 @@ class _FixSSAVars(_BaseHandler):
353
353
  value=rhs,
354
354
  loc=assign.loc,
355
355
  )
356
- elif isinstance(rhs, ir.Var):
356
+ elif isinstance(rhs, ir.var_types):
357
357
  newdef = self._fix_var(states, assign, [rhs])
358
358
  # Has a replacement that is not the current variable
359
359
  if newdef is not None and newdef.target is not ir.UNDEFINED:
@@ -55,8 +55,8 @@ def _extract_loop_lifting_candidates(cfg, blocks):
55
55
  insiders = set(loop.body) | set(loop.entries) | set(loop.exits)
56
56
  for blk in map(blocks.__getitem__, insiders):
57
57
  for inst in blk.body:
58
- if isinstance(inst, ir.Assign):
59
- if isinstance(inst.value, ir.Yield):
58
+ if isinstance(inst, ir.assign_types):
59
+ if isinstance(inst.value, ir.yield_types):
60
60
  _logger.debug("has yield")
61
61
  return False
62
62
  _logger.debug("no yield")
@@ -347,14 +347,14 @@ def canonicalize_cfg_single_backedge(blocks):
347
347
  def replace(target):
348
348
  return dst if target == src else target
349
349
 
350
- if isinstance(term, ir.Branch):
350
+ if isinstance(term, ir.branch_types):
351
351
  return ir.Branch(
352
352
  cond=term.cond,
353
353
  truebr=replace(term.truebr),
354
354
  falsebr=replace(term.falsebr),
355
355
  loc=term.loc,
356
356
  )
357
- elif isinstance(term, ir.Jump):
357
+ elif isinstance(term, ir.jump_types):
358
358
  return ir.Jump(target=replace(term.target), loc=term.loc)
359
359
  else:
360
360
  assert not term.get_targets()
@@ -477,7 +477,7 @@ def _get_with_contextmanager(func_ir, blocks, blk_start):
477
477
  """
478
478
  # If the contextmanager used as a Call
479
479
  dfn = func_ir.get_definition(var_ref)
480
- if isinstance(dfn, ir.Expr) and dfn.op == "call":
480
+ if isinstance(dfn, ir.expr_types) and dfn.op == "call":
481
481
  args = [get_var_dfn(x) for x in dfn.args]
482
482
  kws = {k: get_var_dfn(v) for k, v in dfn.kws}
483
483
  extra = {"args": args, "kwargs": kws}
@@ -501,7 +501,7 @@ def _get_with_contextmanager(func_ir, blocks, blk_start):
501
501
 
502
502
  # Scan the start of the with-region for the contextmanager
503
503
  for stmt in blocks[blk_start].body:
504
- if isinstance(stmt, ir.EnterWith):
504
+ if isinstance(stmt, ir.enterwith_types):
505
505
  var_ref = stmt.contextmanager
506
506
  ctxobj, extra = get_ctxmgr_obj(var_ref)
507
507
  if not hasattr(ctxobj, "mutate_with_body"):
@@ -523,7 +523,22 @@ def _legalize_with_head(blk):
523
523
  """
524
524
  counters = defaultdict(int)
525
525
  for stmt in blk.body:
526
- counters[type(stmt)] += 1
526
+ # The counters dict is keyed on the IR node type. As the rest of the
527
+ # function pops out specific node types, we normalize these node types
528
+ # to be the Numba-CUDA versions of them so that we don't have to have
529
+ # more complicated logic looking for both Numba and Numba-CUDA IR nodes
530
+ # of the same kind.
531
+ if isinstance(stmt, ir.enterwith_types):
532
+ stmt_type = ir.EnterWith
533
+ elif isinstance(stmt, ir.jump_types):
534
+ stmt_type = ir.Jump
535
+ elif isinstance(stmt, ir.del_types):
536
+ stmt_type = ir.Del
537
+ else:
538
+ stmt_type = type(stmt)
539
+
540
+ counters[stmt_type] += 1
541
+
527
542
  if counters.pop(ir.EnterWith) != 1:
528
543
  raise errors.CompilerError(
529
544
  "with's head-block must have exactly 1 ENTER_WITH",
@@ -744,10 +759,10 @@ def _rewrite_return(func_ir, target_block_label):
744
759
  # JUMP
745
760
  # -----------------
746
761
  top_body, bottom_body = [], []
747
- pop_blocks = [*target_block.find_insts(ir.PopBlock)]
762
+ pop_blocks = [*target_block.find_insts(ir.popblock_types)]
748
763
  assert len(pop_blocks) == 1
749
- assert len([*target_block.find_insts(ir.Jump)]) == 1
750
- assert isinstance(target_block.body[-1], ir.Jump)
764
+ assert len([*target_block.find_insts(ir.jump_types)]) == 1
765
+ assert isinstance(target_block.body[-1], ir.jump_types)
751
766
  pb_marker = pop_blocks[0]
752
767
  pb_is = target_block.body.index(pb_marker)
753
768
  top_body.extend(target_block.body[:pb_is])
@@ -166,15 +166,15 @@ class BaseTypeInference(FunctionPass):
166
166
  argvars = set()
167
167
  for bid, blk in interp.blocks.items():
168
168
  for inst in blk.body:
169
- if isinstance(inst, ir.Return):
169
+ if isinstance(inst, ir.return_types):
170
170
  retstmts.append(inst.value.name)
171
- elif isinstance(inst, ir.Assign):
171
+ elif isinstance(inst, ir.assign_types):
172
172
  if (
173
- isinstance(inst.value, ir.Expr)
173
+ isinstance(inst.value, ir.expr_types)
174
174
  and inst.value.op == "cast"
175
175
  ):
176
176
  caststmts[inst.target.name] = inst.value
177
- elif isinstance(inst.value, ir.Arg):
177
+ elif isinstance(inst.value, ir.arg_types):
178
178
  argvars.add(inst.target.name)
179
179
 
180
180
  assert retstmts, "No return statements?"
@@ -518,9 +518,9 @@ class InlineOverloads(FunctionPass):
518
518
  label, block = work_list.pop()
519
519
  for i, instr in enumerate(block.body):
520
520
  # TO-DO: other statements (setitem)
521
- if isinstance(instr, ir.Assign):
521
+ if isinstance(instr, ir.assign_types):
522
522
  expr = instr.value
523
- if isinstance(expr, ir.Expr):
523
+ if isinstance(expr, ir.expr_types):
524
524
  workfn = self._do_work_expr
525
525
 
526
526
  if guard(
@@ -822,8 +822,8 @@ class PreLowerStripPhis(FunctionPass):
822
822
  phis = set()
823
823
  # Find all variables that needs to be exported
824
824
  for label, block in func_ir.blocks.items():
825
- for assign in block.find_insts(ir.Assign):
826
- if isinstance(assign.value, ir.Expr):
825
+ for assign in block.find_insts(ir.assign_types):
826
+ if isinstance(assign.value, ir.expr_types):
827
827
  if assign.value.op == "phi":
828
828
  phis.add(assign)
829
829
  phi = assign.value
@@ -854,7 +854,7 @@ class PreLowerStripPhis(FunctionPass):
854
854
  # last assignment to rhs
855
855
  assignments = [
856
856
  stmt
857
- for stmt in newblk.find_insts(ir.Assign)
857
+ for stmt in newblk.find_insts(ir.assign_types)
858
858
  if stmt.target == rhs
859
859
  ]
860
860
  if assignments:
@@ -653,7 +653,7 @@ class CallConstraint(object):
653
653
  unsatisfied = set()
654
654
  for idx in e.requested_args:
655
655
  maybe_arg = typeinfer.func_ir.get_definition(folded[idx])
656
- if isinstance(maybe_arg, ir.Arg):
656
+ if isinstance(maybe_arg, ir.arg_types):
657
657
  requested.add(maybe_arg.index)
658
658
  else:
659
659
  unsatisfied.add(idx)
@@ -1081,7 +1081,7 @@ class TypeInferer(object):
1081
1081
  rets = []
1082
1082
  for blk in self.blocks.values():
1083
1083
  inst = blk.terminator
1084
- if isinstance(inst, ir.Return):
1084
+ if isinstance(inst, ir.return_types):
1085
1085
  rets.append(inst.value)
1086
1086
  return rets
1087
1087
 
@@ -1241,7 +1241,7 @@ https://numba.readthedocs.io/en/stable/user/troubleshoot.html#my-code-has-an-unt
1241
1241
  call_name = offender.value.func.name
1242
1242
  # find the offender based on the call name
1243
1243
  offender = find_offender(call_name)
1244
- if isinstance(offender.value, ir.Global):
1244
+ if isinstance(offender.value, ir.global_types):
1245
1245
  if offender.value.name == "list":
1246
1246
  return list_msg
1247
1247
  except (AttributeError, KeyError):
@@ -1447,9 +1447,9 @@ https://numba.readthedocs.io/en/stable/user/troubleshoot.html#my-code-has-an-unt
1447
1447
  returns = {}
1448
1448
  for x in reversed(lst):
1449
1449
  for block in self.func_ir.blocks.values():
1450
- for instr in block.find_insts(ir.Return):
1450
+ for instr in block.find_insts(ir.return_types):
1451
1451
  value = instr.value
1452
- if isinstance(value, ir.Var):
1452
+ if isinstance(value, ir.var_types):
1453
1453
  name = value.name
1454
1454
  else:
1455
1455
  pass
@@ -1497,27 +1497,37 @@ https://numba.readthedocs.io/en/stable/user/troubleshoot.html#my-code-has-an-unt
1497
1497
  return [tv.type for name, tv in sorted(self.typevars.items())]
1498
1498
 
1499
1499
  def constrain_statement(self, inst):
1500
- if isinstance(inst, ir.Assign):
1500
+ if isinstance(inst, ir.assign_types):
1501
1501
  self.typeof_assign(inst)
1502
- elif isinstance(inst, ir.SetItem):
1502
+ elif isinstance(inst, ir.setitem_types):
1503
1503
  self.typeof_setitem(inst)
1504
- elif isinstance(inst, ir.StaticSetItem):
1504
+ elif isinstance(inst, ir.staticsetitem_types):
1505
1505
  self.typeof_static_setitem(inst)
1506
- elif isinstance(inst, ir.DelItem):
1506
+ elif isinstance(inst, ir.delitem_types):
1507
1507
  self.typeof_delitem(inst)
1508
- elif isinstance(inst, ir.SetAttr):
1508
+ elif isinstance(inst, ir.setattr_types):
1509
1509
  self.typeof_setattr(inst)
1510
- elif isinstance(inst, ir.Print):
1510
+ elif isinstance(inst, ir.print_types):
1511
1511
  self.typeof_print(inst)
1512
- elif isinstance(inst, ir.StoreMap):
1512
+ elif isinstance(inst, ir.storemap_types):
1513
1513
  self.typeof_storemap(inst)
1514
- elif isinstance(inst, (ir.Jump, ir.Branch, ir.Return, ir.Del)):
1514
+ elif isinstance(inst, ir.jump_types):
1515
1515
  pass
1516
- elif isinstance(inst, (ir.DynamicRaise, ir.DynamicTryRaise)):
1516
+ elif isinstance(inst, ir.branch_types):
1517
1517
  pass
1518
- elif isinstance(inst, (ir.StaticRaise, ir.StaticTryRaise)):
1518
+ elif isinstance(inst, ir.return_types):
1519
1519
  pass
1520
- elif isinstance(inst, ir.PopBlock):
1520
+ elif isinstance(inst, ir.del_types):
1521
+ pass
1522
+ elif isinstance(inst, ir.dynamicraise_types):
1523
+ pass
1524
+ elif isinstance(inst, ir.dynamictryraise_types):
1525
+ pass
1526
+ elif isinstance(inst, ir.staticraise_types):
1527
+ pass
1528
+ elif isinstance(inst, ir.statictryraise_types):
1529
+ pass
1530
+ elif isinstance(inst, ir.popblock_types):
1521
1531
  pass # It's a marker statement
1522
1532
  elif type(inst) in typeinfer_extensions:
1523
1533
  # let external calls handle stmt if type matches
@@ -1575,19 +1585,21 @@ https://numba.readthedocs.io/en/stable/user/troubleshoot.html#my-code-has-an-unt
1575
1585
 
1576
1586
  def typeof_assign(self, inst):
1577
1587
  value = inst.value
1578
- if isinstance(value, ir.Const):
1588
+ if isinstance(value, ir.const_types):
1579
1589
  self.typeof_const(inst, inst.target, value.value)
1580
- elif isinstance(value, ir.Var):
1590
+ elif isinstance(value, ir.var_types):
1581
1591
  self.constraints.append(
1582
1592
  Propagate(dst=inst.target.name, src=value.name, loc=inst.loc)
1583
1593
  )
1584
- elif isinstance(value, (ir.Global, ir.FreeVar)):
1594
+ elif isinstance(value, ir.global_types) or isinstance(
1595
+ value, ir.freevar_types
1596
+ ):
1585
1597
  self.typeof_global(inst, inst.target, value)
1586
- elif isinstance(value, ir.Arg):
1598
+ elif isinstance(value, ir.arg_types):
1587
1599
  self.typeof_arg(inst, inst.target, value)
1588
- elif isinstance(value, ir.Expr):
1600
+ elif isinstance(value, ir.expr_types):
1589
1601
  self.typeof_expr(inst, inst.target, value)
1590
- elif isinstance(value, ir.Yield):
1602
+ elif isinstance(value, ir.yield_types):
1591
1603
  self.typeof_yield(inst, inst.target, value)
1592
1604
  else:
1593
1605
  msg = "Unsupported assignment encountered: %s %s" % (
@@ -1738,8 +1750,11 @@ https://numba.readthedocs.io/en/stable/user/troubleshoot.html#my-code-has-an-unt
1738
1750
  )
1739
1751
 
1740
1752
  if isinstance(typ, types.Array):
1741
- # Global array in nopython mode is constant
1742
- typ = typ.copy(readonly=True)
1753
+ # Global array in nopython mode is constant, except for device
1754
+ # arrays implementing __cuda_array_interface__ which are references
1755
+ # to mutable device memory
1756
+ if not hasattr(gvar.value, "__cuda_array_interface__"):
1757
+ typ = typ.copy(readonly=True)
1743
1758
 
1744
1759
  if isinstance(typ, types.BaseAnonymousTuple):
1745
1760
  # if it's a tuple of literal types, swap the type for the more