Repository: numba/numba

Issue:
Datashader/Numba various LoweringErrors
- [x] I am using `'0.50.0dev0+71.gce2139c'` installed from the numba channel on anaconda.org
- [x] I have included below a minimal working reproducer

Steps to reproduce:

* Setup a development environment with Datashader `v0.11.0a1` and the Numba version listed above.
* Run `pytest datashader/tests/test_raster.py`

As far as I can tell, errors all seem to be of the form:

```
E       numba.core.errors.LoweringError: Failed in nopython mode pipeline (step: nopython mode backend)
E       Buffer dtype cannot be buffer, have dtype: array(float32, 2d, C)
E       
E       File "datashader/resampling.py", line 901:
E       def _downsample_2d_std_var(src, mask, use_mask, method, fill_value,
E           <source elided>
E       
E           for out_y in prange(out_h):
E           ^
E       
```

Log file is attached.

[datashader_numba_error.log](https://github.com/numba/numba/files/4485685/datashader_numba_error.log)

Datashader/Numba various LoweringErrors
- [x] I am using `'0.50.0dev0+71.gce2139c'` installed from the numba channel on anaconda.org
- [x] I have included below a minimal working reproducer

Steps to reproduce:

* Setup a development environment with Datashader `v0.11.0a1` and the Numba version listed above.
* Run `pytest datashader/tests/test_raster.py`

As far as I can tell, errors all seem to be of the form:

```
E       numba.core.errors.LoweringError: Failed in nopython mode pipeline (step: nopython mode backend)
E       Buffer dtype cannot be buffer, have dtype: array(float32, 2d, C)
E       
E       File "datashader/resampling.py", line 901:
E       def _downsample_2d_std_var(src, mask, use_mask, method, fill_value,
E           <source elided>
E       
E           for out_y in prange(out_h):
E           ^
E       
```

Log file is attached.

[datashader_numba_error.log](https://github.com/numba/numba/files/4485685/datashader_numba_error.log)



Discussion:
Further investigations have concluded that the test/code works fine if I either remove the Numba `njit` decoration or when switching from `prange` to `range`. Presume it is a parfors error.
```
During: lowering "id=59[LoopNest(index_variable = parfor_index.9263, range = (0, $out_h.9270, 1))]
```
^ that's a parfors node.
Perhaps have a look at the source triggering this problem, might be an array constructor with a list of arrays as the arg.
I have extracted a reproducer from the failing unit test, it might make it easier to spot what is going on:

```python
from numba import njit, prange
import numpy as np

DS_STD = 58
_EPS = 1e-10

@njit(nogil=True)
def _get_dimensions(src, out):
    src_w = src.shape[-1]
    src_h = src.shape[-2]
    out_w = out.shape[-1]
    out_h = out.shape[-2]
    return src_w, src_h, out_w, out_h

@njit(nogil=True, parallel=True)
def _downsample_2d_std_var(src, mask, use_mask, method, fill_value,
                           mode_rank, x_offset, y_offset, out):
    src_w, src_h, out_w, out_h = _get_dimensions(src, out)

    if src_w == out_w and src_h == out_h:
        return src

    if out_w > src_w or out_h > src_h:
        raise ValueError("invalid target size")

    x0_off, x1_off = x_offset
    y0_off, y1_off = y_offset
    scale_x = (src_w - x0_off - x1_off) / out_w
    scale_y = (src_h - y0_off - y1_off) / out_h
    for out_y in prange(out_h):
        src_yf0 = (scale_y * out_y) + y0_off
        src_yf1 = src_yf0 + scale_y
        src_y0 = int(src_yf0)
        src_y1 = int(src_yf1)
        wy0 = 1.0 - (src_yf0 - src_y0)
        wy1 = src_yf1 - src_y1
        if wy1 < _EPS:
            wy1 = 1.0
            if src_y1 > src_y0:
                src_y1 -= 1
        for out_x in range(out_w):
            src_xf0 = (scale_x * out_x) + x0_off
            src_xf1 = src_xf0 + scale_x
            src_x0 = int(src_xf0)
            src_x1 = int(src_xf1)
            wx0 = 1.0 - (src_xf0 - src_x0)
            wx1 = src_xf1 - src_x1
            if wx1 < _EPS:
                wx1 = 1.0
                if src_x1 > src_x0:
                    src_x1 -= 1
            v_sum = 0.0
            w_sum = 0.0
            wv_sum = 0.0
            wvv_sum = 0.0
            for src_y in range(src_y0, src_y1 + 1):
                wy = wy0 if (src_y == src_y0) else wy1 if (src_y == src_y1) else 1.0
                for src_x in range(src_x0, src_x1 + 1):
                    wx = wx0 if (src_x == src_x0) else wx1 if (src_x == src_x1) else 1.0
                    v = src[src_y, src_x]
                    if np.isfinite(v) and not (use_mask and mask[src_y, src_x]):
                        w = wx * wy
                        v_sum += v
                        w_sum += w
                        wv_sum += w * v
                        wvv_sum += w * v * v
            if w_sum < _EPS:
                out[out_y, out_x] = fill_value
            else:
                out[out_y, out_x] = (wvv_sum * w_sum - wv_sum * wv_sum) / w_sum / w_sum
    if method == DS_STD:
        out = np.sqrt(out)
    return out

src = np.array([[ 0.84147096,  0.47942555, -0.        , -0.47942555, -0.84147096],
       [ 0.47942555,  0.24740396, -0.        , -0.24740396, -0.47942555],
       [-0.        , -0.        ,  0.        ,  0.        ,  0.        ],
       [-0.47942555, -0.24740396,  0.        ,  0.24740396,  0.47942555],
       [-0.84147096, -0.47942555,  0.        ,  0.47942555,  0.84147096]],
      dtype=np.float32)
mask = np.array([[False]])
use_mask = False
method = 57
fill_value = np.nan
mode_rank = 1
x_offset = (0, 0)
y_offset = (0, 0)
out = np.array([[0., 0.],
       [0., 0.]], dtype=np.float32)

_downsample_2d_std_var(src,
                       mask,
                       use_mask,
                       method,
                       fill_value,
                       mode_rank,
                       x_offset,
                       y_offset,
                       out
                      )
```

The error log is also shorter:

```
/Users/vhaenel/git/numba/numba/parfors/parfor_lowering.py:933: NumbaParallelSafetyWarning: Variable out.4 used in parallel loop may be written to simultaneously by multiple workers and may result in non-deterministic or unintended results.

File "foo036.py", line 30:
def _downsample_2d_std_var(src, mask, use_mask, method, fill_value,
    <source elided>
    scale_y = (src_h - y0_off - y1_off) / out_h
    for out_y in prange(out_h):
    ^

  warnings.warn(NumbaParallelSafetyWarning(msg, loc))
Traceback (most recent call last):
  File "/Users/vhaenel/git/numba/numba/core/errors.py", line 801, in new_error_context
    yield
  File "/Users/vhaenel/git/numba/numba/core/lowering.py", line 267, in lower_block
    self.lower_inst(inst)
  File "/Users/vhaenel/git/numba/numba/core/lowering.py", line 480, in lower_inst
    func(self, inst)
  File "/Users/vhaenel/git/numba/numba/parfors/parfor_lowering.py", line 238, in _lower_parfor_parallel
    exp_name_to_tuple_var) = _create_gufunc_for_parfor_body(
  File "/Users/vhaenel/git/numba/numba/parfors/parfor_lowering.py", line 934, in _create_gufunc_for_parfor_body
    replace_var_with_array(races, loop_body, typemap, lowerer.fndesc.calltypes)
  File "/Users/vhaenel/git/numba/numba/parfors/parfor_lowering.py", line 1368, in replace_var_with_array
    typemap[v] = types.npytypes.Array(el_typ, 1, "C")
  File "/Users/vhaenel/git/numba/numba/core/types/abstract.py", line 65, in __call__
    inst = type.__call__(cls, *args, **kwargs)
  File "/Users/vhaenel/git/numba/numba/core/types/npytypes.py", line 411, in __init__
    super(Array, self).__init__(dtype, ndim, layout, name=name)
  File "/Users/vhaenel/git/numba/numba/core/types/common.py", line 52, in __init__
    raise TypeError("Buffer dtype cannot be buffer, have dtype: {}".format(dtype))
TypeError: Buffer dtype cannot be buffer, have dtype: array(float32, 2d, C)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "foo036.py", line 91, in <module>
    _downsample_2d_std_var(src,
  File "/Users/vhaenel/git/numba/numba/core/dispatcher.py", line 420, in _compile_for_args
    raise e
  File "/Users/vhaenel/git/numba/numba/core/dispatcher.py", line 353, in _compile_for_args
    return self.compile(tuple(argtypes))
  File "/Users/vhaenel/git/numba/numba/core/compiler_lock.py", line 32, in _acquire_compile_lock
    return func(*args, **kwargs)
  File "/Users/vhaenel/git/numba/numba/core/dispatcher.py", line 794, in compile
    cres = self._compiler.compile(args, return_type)
  File "/Users/vhaenel/git/numba/numba/core/dispatcher.py", line 77, in compile
    status, retval = self._compile_cached(args, return_type)
  File "/Users/vhaenel/git/numba/numba/core/dispatcher.py", line 91, in _compile_cached
    retval = self._compile_core(args, return_type)
  File "/Users/vhaenel/git/numba/numba/core/dispatcher.py", line 104, in _compile_core
    cres = compiler.compile_extra(self.targetdescr.typing_context,
  File "/Users/vhaenel/git/numba/numba/core/compiler.py", line 568, in compile_extra
    return pipeline.compile_extra(func)
  File "/Users/vhaenel/git/numba/numba/core/compiler.py", line 339, in compile_extra
    return self._compile_bytecode()
  File "/Users/vhaenel/git/numba/numba/core/compiler.py", line 401, in _compile_bytecode
    return self._compile_core()
  File "/Users/vhaenel/git/numba/numba/core/compiler.py", line 381, in _compile_core
    raise e
  File "/Users/vhaenel/git/numba/numba/core/compiler.py", line 372, in _compile_core
    pm.run(self.state)
  File "/Users/vhaenel/git/numba/numba/core/compiler_machinery.py", line 341, in run
    raise patched_exception
  File "/Users/vhaenel/git/numba/numba/core/compiler_machinery.py", line 332, in run
    self._runPass(idx, pass_inst, state)
  File "/Users/vhaenel/git/numba/numba/core/compiler_lock.py", line 32, in _acquire_compile_lock
    return func(*args, **kwargs)
  File "/Users/vhaenel/git/numba/numba/core/compiler_machinery.py", line 291, in _runPass
    mutated |= check(pss.run_pass, internal_state)
  File "/Users/vhaenel/git/numba/numba/core/compiler_machinery.py", line 264, in check
    mangled = func(compiler_state)
  File "/Users/vhaenel/git/numba/numba/core/typed_passes.py", line 442, in run_pass
    NativeLowering().run_pass(state)
  File "/Users/vhaenel/git/numba/numba/core/typed_passes.py", line 370, in run_pass
    lower.lower()
  File "/Users/vhaenel/git/numba/numba/core/lowering.py", line 179, in lower
    self.lower_normal_function(self.fndesc)
  File "/Users/vhaenel/git/numba/numba/core/lowering.py", line 227, in lower_normal_function
    entry_block_tail = self.lower_function_body()
  File "/Users/vhaenel/git/numba/numba/core/lowering.py", line 253, in lower_function_body
    self.lower_block(block)
  File "/Users/vhaenel/git/numba/numba/core/lowering.py", line 267, in lower_block
    self.lower_inst(inst)
  File "/Users/vhaenel/miniconda3/envs/numba_3.8/lib/python3.8/contextlib.py", line 131, in __exit__
    self.gen.throw(type, value, traceback)
  File "/Users/vhaenel/git/numba/numba/core/errors.py", line 808, in new_error_context
    reraise(type(newerr), newerr, tb)
  File "/Users/vhaenel/git/numba/numba/core/utils.py", line 79, in reraise
    raise value.with_traceback(tb)
  File "/Users/vhaenel/git/numba/numba/core/errors.py", line 801, in new_error_context
    yield
  File "/Users/vhaenel/git/numba/numba/core/lowering.py", line 267, in lower_block
    self.lower_inst(inst)
  File "/Users/vhaenel/git/numba/numba/core/lowering.py", line 480, in lower_inst
    func(self, inst)
  File "/Users/vhaenel/git/numba/numba/parfors/parfor_lowering.py", line 238, in _lower_parfor_parallel
    exp_name_to_tuple_var) = _create_gufunc_for_parfor_body(
  File "/Users/vhaenel/git/numba/numba/parfors/parfor_lowering.py", line 934, in _create_gufunc_for_parfor_body
    replace_var_with_array(races, loop_body, typemap, lowerer.fndesc.calltypes)
  File "/Users/vhaenel/git/numba/numba/parfors/parfor_lowering.py", line 1368, in replace_var_with_array
    typemap[v] = types.npytypes.Array(el_typ, 1, "C")
  File "/Users/vhaenel/git/numba/numba/core/types/abstract.py", line 65, in __call__
    inst = type.__call__(cls, *args, **kwargs)
  File "/Users/vhaenel/git/numba/numba/core/types/npytypes.py", line 411, in __init__
    super(Array, self).__init__(dtype, ndim, layout, name=name)
  File "/Users/vhaenel/git/numba/numba/core/types/common.py", line 52, in __init__
    raise TypeError("Buffer dtype cannot be buffer, have dtype: {}".format(dtype))
numba.core.errors.LoweringError: Failed in nopython mode pipeline (step: nopython mode backend)
Buffer dtype cannot be buffer, have dtype: array(float32, 2d, C)

File "foo036.py", line 30:
def _downsample_2d_std_var(src, mask, use_mask, method, fill_value,
    <source elided>
    scale_y = (src_h - y0_off - y1_off) / out_h
    for out_y in prange(out_h):
    ^

[1] During: lowering "id=1[LoopNest(index_variable = parfor_index.46, range = (0, $out_h.53, 1))]{392: <ir.Block at foo036.py (58)>, 394: <ir.Block at foo036.py (58)>, 528: <ir.Block at foo036.py (58)>, 532: <ir.Block at foo036.py (66)>, 406: <ir.Block at foo036.py (59)>, 410: <ir.Block at foo036.py (59)>, 542: <ir.Block at foo036.py (67)>, 290: <ir.Block at foo036.py (49)>, 420: <ir.Block at foo036.py (59)>, 424: <ir.Block at foo036.py (59)>, 426: <ir.Block at foo036.py (59)>, 556: <ir.Block at foo036.py (68)>, 304: <ir.Block at foo036.py (51)>, 312: <ir.Block at foo036.py (52)>, 190: <ir.Block at foo036.py (38)>, 452: <ir.Block at foo036.py (61)>, 202: <ir.Block at foo036.py (40)>, 458: <ir.Block at foo036.py (61)>, 590: <ir.Block at foo036.py (70)>, 592: <ir.Block at foo036.py (41)>, 210: <ir.Block at foo036.py (41)>, 342: <ir.Block at foo036.py (56)>, 472: <ir.Block at foo036.py (62)>, 344: <ir.Block at foo036.py (56)>, 602: <ir.Block at foo036.py (70)>, 218: <ir.Block at foo036.py (41)>, 222: <ir.Block at foo036.py (41)>, 376: <ir.Block at foo036.py (57)>, 356: <ir.Block at foo036.py (57)>, 360: <ir.Block at foo036.py (57)>, 370: <ir.Block at foo036.py (57)>, 374: <ir.Block at foo036.py (57)>, 124: <ir.Block at foo036.py (30)>}Var(parfor_index.46, foo036.py:30)" at foo036.py (30)
```
MWR:
```python
from numba import njit, prange
import numpy as np

@njit(nogil=True, parallel=True)
def foo(src, method, out):
    for i in prange(1):
        for j in range(1):
            out[i, j] = 1
    if method:
        out += 1
    return out

src = np.zeros((5,5))
method = 57
out = np.zeros((2, 2))

foo(src, method, out)
```
things that influence it are:
* whether the branch on `method` is present
* whether the inner loop is present

@stuartarchibald oh awesome! Thanks for extracting that one!!

@sklam I can verify this works with 0.48.0 but is broken with 0.49.0.
Ok, so very likely SSA issue.
Further investigations have concluded that the test/code works fine if I either remove the Numba `njit` decoration or when switching from `prange` to `range`. Presume it is a parfors error.
```
During: lowering "id=59[LoopNest(index_variable = parfor_index.9263, range = (0, $out_h.9270, 1))]
```
^ that's a parfors node.
Perhaps have a look at the source triggering this problem, might be an array constructor with a list of arrays as the arg.
I have extracted a reproducer from the failing unit test, it might make it easier to spot what is going on:

```python
from numba import njit, prange
import numpy as np

DS_STD = 58
_EPS = 1e-10

@njit(nogil=True)
def _get_dimensions(src, out):
    src_w = src.shape[-1]
    src_h = src.shape[-2]
    out_w = out.shape[-1]
    out_h = out.shape[-2]
    return src_w, src_h, out_w, out_h

@njit(nogil=True, parallel=True)
def _downsample_2d_std_var(src, mask, use_mask, method, fill_value,
                           mode_rank, x_offset, y_offset, out):
    src_w, src_h, out_w, out_h = _get_dimensions(src, out)

    if src_w == out_w and src_h == out_h:
        return src

    if out_w > src_w or out_h > src_h:
        raise ValueError("invalid target size")

    x0_off, x1_off = x_offset
    y0_off, y1_off = y_offset
    scale_x = (src_w - x0_off - x1_off) / out_w
    scale_y = (src_h - y0_off - y1_off) / out_h
    for out_y in prange(out_h):
        src_yf0 = (scale_y * out_y) + y0_off
        src_yf1 = src_yf0 + scale_y
        src_y0 = int(src_yf0)
        src_y1 = int(src_yf1)
        wy0 = 1.0 - (src_yf0 - src_y0)
        wy1 = src_yf1 - src_y1
        if wy1 < _EPS:
            wy1 = 1.0
            if src_y1 > src_y0:
                src_y1 -= 1
        for out_x in range(out_w):
            src_xf0 = (scale_x * out_x) + x0_off
            src_xf1 = src_xf0 + scale_x
            src_x0 = int(src_xf0)
            src_x1 = int(src_xf1)
            wx0 = 1.0 - (src_xf0 - src_x0)
            wx1 = src_xf1 - src_x1
            if wx1 < _EPS:
                wx1 = 1.0
                if src_x1 > src_x0:
                    src_x1 -= 1
            v_sum = 0.0
            w_sum = 0.0
            wv_sum = 0.0
            wvv_sum = 0.0
            for src_y in range(src_y0, src_y1 + 1):
                wy = wy0 if (src_y == src_y0) else wy1 if (src_y == src_y1) else 1.0
                for src_x in range(src_x0, src_x1 + 1):
                    wx = wx0 if (src_x == src_x0) else wx1 if (src_x == src_x1) else 1.0
                    v = src[src_y, src_x]
                    if np.isfinite(v) and not (use_mask and mask[src_y, src_x]):
                        w = wx * wy
                        v_sum += v
                        w_sum += w
                        wv_sum += w * v
                        wvv_sum += w * v * v
            if w_sum < _EPS:
                out[out_y, out_x] = fill_value
            else:
                out[out_y, out_x] = (wvv_sum * w_sum - wv_sum * wv_sum) / w_sum / w_sum
    if method == DS_STD:
        out = np.sqrt(out)
    return out

src = np.array([[ 0.84147096,  0.47942555, -0.        , -0.47942555, -0.84147096],
       [ 0.47942555,  0.24740396, -0.        , -0.24740396, -0.47942555],
       [-0.        , -0.        ,  0.        ,  0.        ,  0.        ],
       [-0.47942555, -0.24740396,  0.        ,  0.24740396,  0.47942555],
       [-0.84147096, -0.47942555,  0.        ,  0.47942555,  0.84147096]],
      dtype=np.float32)
mask = np.array([[False]])
use_mask = False
method = 57
fill_value = np.nan
mode_rank = 1
x_offset = (0, 0)
y_offset = (0, 0)
out = np.array([[0., 0.],
       [0., 0.]], dtype=np.float32)

_downsample_2d_std_var(src,
                       mask,
                       use_mask,
                       method,
                       fill_value,
                       mode_rank,
                       x_offset,
                       y_offset,
                       out
                      )
```

The error log is also shorter:

```
/Users/vhaenel/git/numba/numba/parfors/parfor_lowering.py:933: NumbaParallelSafetyWarning: Variable out.4 used in parallel loop may be written to simultaneously by multiple workers and may result in non-deterministic or unintended results.

File "foo036.py", line 30:
def _downsample_2d_std_var(src, mask, use_mask, method, fill_value,
    <source elided>
    scale_y = (src_h - y0_off - y1_off) / out_h
    for out_y in prange(out_h):
    ^

  warnings.warn(NumbaParallelSafetyWarning(msg, loc))
Traceback (most recent call last):
  File "/Users/vhaenel/git/numba/numba/core/errors.py", line 801, in new_error_context
    yield
  File "/Users/vhaenel/git/numba/numba/core/lowering.py", line 267, in lower_block
    self.lower_inst(inst)
  File "/Users/vhaenel/git/numba/numba/core/lowering.py", line 480, in lower_inst
    func(self, inst)
  File "/Users/vhaenel/git/numba/numba/parfors/parfor_lowering.py", line 238, in _lower_parfor_parallel
    exp_name_to_tuple_var) = _create_gufunc_for_parfor_body(
  File "/Users/vhaenel/git/numba/numba/parfors/parfor_lowering.py", line 934, in _create_gufunc_for_parfor_body
    replace_var_with_array(races, loop_body, typemap, lowerer.fndesc.calltypes)
  File "/Users/vhaenel/git/numba/numba/parfors/parfor_lowering.py", line 1368, in replace_var_with_array
    typemap[v] = types.npytypes.Array(el_typ, 1, "C")
  File "/Users/vhaenel/git/numba/numba/core/types/abstract.py", line 65, in __call__
    inst = type.__call__(cls, *args, **kwargs)
  File "/Users/vhaenel/git/numba/numba/core/types/npytypes.py", line 411, in __init__
    super(Array, self).__init__(dtype, ndim, layout, name=name)
  File "/Users/vhaenel/git/numba/numba/core/types/common.py", line 52, in __init__
    raise TypeError("Buffer dtype cannot be buffer, have dtype: {}".format(dtype))
TypeError: Buffer dtype cannot be buffer, have dtype: array(float32, 2d, C)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "foo036.py", line 91, in <module>
    _downsample_2d_std_var(src,
  File "/Users/vhaenel/git/numba/numba/core/dispatcher.py", line 420, in _compile_for_args
    raise e
  File "/Users/vhaenel/git/numba/numba/core/dispatcher.py", line 353, in _compile_for_args
    return self.compile(tuple(argtypes))
  File "/Users/vhaenel/git/numba/numba/core/compiler_lock.py", line 32, in _acquire_compile_lock
    return func(*args, **kwargs)
  File "/Users/vhaenel/git/numba/numba/core/dispatcher.py", line 794, in compile
    cres = self._compiler.compile(args, return_type)
  File "/Users/vhaenel/git/numba/numba/core/dispatcher.py", line 77, in compile
    status, retval = self._compile_cached(args, return_type)
  File "/Users/vhaenel/git/numba/numba/core/dispatcher.py", line 91, in _compile_cached
    retval = self._compile_core(args, return_type)
  File "/Users/vhaenel/git/numba/numba/core/dispatcher.py", line 104, in _compile_core
    cres = compiler.compile_extra(self.targetdescr.typing_context,
  File "/Users/vhaenel/git/numba/numba/core/compiler.py", line 568, in compile_extra
    return pipeline.compile_extra(func)
  File "/Users/vhaenel/git/numba/numba/core/compiler.py", line 339, in compile_extra
    return self._compile_bytecode()
  File "/Users/vhaenel/git/numba/numba/core/compiler.py", line 401, in _compile_bytecode
    return self._compile_core()
  File "/Users/vhaenel/git/numba/numba/core/compiler.py", line 381, in _compile_core
    raise e
  File "/Users/vhaenel/git/numba/numba/core/compiler.py", line 372, in _compile_core
    pm.run(self.state)
  File "/Users/vhaenel/git/numba/numba/core/compiler_machinery.py", line 341, in run
    raise patched_exception
  File "/Users/vhaenel/git/numba/numba/core/compiler_machinery.py", line 332, in run
    self._runPass(idx, pass_inst, state)
  File "/Users/vhaenel/git/numba/numba/core/compiler_lock.py", line 32, in _acquire_compile_lock
    return func(*args, **kwargs)
  File "/Users/vhaenel/git/numba/numba/core/compiler_machinery.py", line 291, in _runPass
    mutated |= check(pss.run_pass, internal_state)
  File "/Users/vhaenel/git/numba/numba/core/compiler_machinery.py", line 264, in check
    mangled = func(compiler_state)
  File "/Users/vhaenel/git/numba/numba/core/typed_passes.py", line 442, in run_pass
    NativeLowering().run_pass(state)
  File "/Users/vhaenel/git/numba/numba/core/typed_passes.py", line 370, in run_pass
    lower.lower()
  File "/Users/vhaenel/git/numba/numba/core/lowering.py", line 179, in lower
    self.lower_normal_function(self.fndesc)
  File "/Users/vhaenel/git/numba/numba/core/lowering.py", line 227, in lower_normal_function
    entry_block_tail = self.lower_function_body()
  File "/Users/vhaenel/git/numba/numba/core/lowering.py", line 253, in lower_function_body
    self.lower_block(block)
  File "/Users/vhaenel/git/numba/numba/core/lowering.py", line 267, in lower_block
    self.lower_inst(inst)
  File "/Users/vhaenel/miniconda3/envs/numba_3.8/lib/python3.8/contextlib.py", line 131, in __exit__
    self.gen.throw(type, value, traceback)
  File "/Users/vhaenel/git/numba/numba/core/errors.py", line 808, in new_error_context
    reraise(type(newerr), newerr, tb)
  File "/Users/vhaenel/git/numba/numba/core/utils.py", line 79, in reraise
    raise value.with_traceback(tb)
  File "/Users/vhaenel/git/numba/numba/core/errors.py", line 801, in new_error_context
    yield
  File "/Users/vhaenel/git/numba/numba/core/lowering.py", line 267, in lower_block
    self.lower_inst(inst)
  File "/Users/vhaenel/git/numba/numba/core/lowering.py", line 480, in lower_inst
    func(self, inst)
  File "/Users/vhaenel/git/numba/numba/parfors/parfor_lowering.py", line 238, in _lower_parfor_parallel
    exp_name_to_tuple_var) = _create_gufunc_for_parfor_body(
  File "/Users/vhaenel/git/numba/numba/parfors/parfor_lowering.py", line 934, in _create_gufunc_for_parfor_body
    replace_var_with_array(races, loop_body, typemap, lowerer.fndesc.calltypes)
  File "/Users/vhaenel/git/numba/numba/parfors/parfor_lowering.py", line 1368, in replace_var_with_array
    typemap[v] = types.npytypes.Array(el_typ, 1, "C")
  File "/Users/vhaenel/git/numba/numba/core/types/abstract.py", line 65, in __call__
    inst = type.__call__(cls, *args, **kwargs)
  File "/Users/vhaenel/git/numba/numba/core/types/npytypes.py", line 411, in __init__
    super(Array, self).__init__(dtype, ndim, layout, name=name)
  File "/Users/vhaenel/git/numba/numba/core/types/common.py", line 52, in __init__
    raise TypeError("Buffer dtype cannot be buffer, have dtype: {}".format(dtype))
numba.core.errors.LoweringError: Failed in nopython mode pipeline (step: nopython mode backend)
Buffer dtype cannot be buffer, have dtype: array(float32, 2d, C)

File "foo036.py", line 30:
def _downsample_2d_std_var(src, mask, use_mask, method, fill_value,
    <source elided>
    scale_y = (src_h - y0_off - y1_off) / out_h
    for out_y in prange(out_h):
    ^

[1] During: lowering "id=1[LoopNest(index_variable = parfor_index.46, range = (0, $out_h.53, 1))]{392: <ir.Block at foo036.py (58)>, 394: <ir.Block at foo036.py (58)>, 528: <ir.Block at foo036.py (58)>, 532: <ir.Block at foo036.py (66)>, 406: <ir.Block at foo036.py (59)>, 410: <ir.Block at foo036.py (59)>, 542: <ir.Block at foo036.py (67)>, 290: <ir.Block at foo036.py (49)>, 420: <ir.Block at foo036.py (59)>, 424: <ir.Block at foo036.py (59)>, 426: <ir.Block at foo036.py (59)>, 556: <ir.Block at foo036.py (68)>, 304: <ir.Block at foo036.py (51)>, 312: <ir.Block at foo036.py (52)>, 190: <ir.Block at foo036.py (38)>, 452: <ir.Block at foo036.py (61)>, 202: <ir.Block at foo036.py (40)>, 458: <ir.Block at foo036.py (61)>, 590: <ir.Block at foo036.py (70)>, 592: <ir.Block at foo036.py (41)>, 210: <ir.Block at foo036.py (41)>, 342: <ir.Block at foo036.py (56)>, 472: <ir.Block at foo036.py (62)>, 344: <ir.Block at foo036.py (56)>, 602: <ir.Block at foo036.py (70)>, 218: <ir.Block at foo036.py (41)>, 222: <ir.Block at foo036.py (41)>, 376: <ir.Block at foo036.py (57)>, 356: <ir.Block at foo036.py (57)>, 360: <ir.Block at foo036.py (57)>, 370: <ir.Block at foo036.py (57)>, 374: <ir.Block at foo036.py (57)>, 124: <ir.Block at foo036.py (30)>}Var(parfor_index.46, foo036.py:30)" at foo036.py (30)
```
MWR:
```python
from numba import njit, prange
import numpy as np

@njit(nogil=True, parallel=True)
def foo(src, method, out):
    for i in prange(1):
        for j in range(1):
            out[i, j] = 1
    if method:
        out += 1
    return out

src = np.zeros((5,5))
method = 57
out = np.zeros((2, 2))

foo(src, method, out)
```
things that influence it are:
* whether the branch on `method` is present
* whether the inner loop is present

@stuartarchibald oh awesome! Thanks for extracting that one!!

@sklam I can verify this works with 0.48.0 but is broken with 0.49.0.
Ok, so very likely SSA issue.

Resolving patch:
diff --git a/numba/parfors/parfor.py b/numba/parfors/parfor.py
--- a/numba/parfors/parfor.py
+++ b/numba/parfors/parfor.py
@@ -3169,7 +3169,12 @@ def get_parfor_params(blocks, options_fusion, fusion_info):
             dummy_block.body = block.body[:i]
             before_defs = compute_use_defs({0: dummy_block}).defmap[0]
             pre_defs |= before_defs
-            parfor.params = get_parfor_params_inner(parfor, pre_defs, options_fusion, fusion_info) | parfor.races
+            params = get_parfor_params_inner(
+                parfor, pre_defs, options_fusion, fusion_info,
+            )
+            parfor.params, parfor.races = _combine_params_races_for_ssa_names(
+                block.scope, params, parfor.races,
+            )
             parfor_ids.add(parfor.id)
             parfors.append(parfor)
 
@@ -3177,6 +3182,30 @@ def get_parfor_params(blocks, options_fusion, fusion_info):
     return parfor_ids, parfors
 
 
+def _combine_params_races_for_ssa_names(scope, params, races):
+    """Returns `(params|races1, races1)`, where `races1` contains all variables
+    in `races` are NOT referring to the same unversioned (SSA) variables in
+    `params`.
+    """
+    def unversion(k):
+        try:
+            return scope.get_exact(k).unversioned_name
+        except ir.NotDefinedError:
+            # XXX: it's a bug that something references an undefined name
+            return k
+
+    races1 = set(races)
+    unver_params = list(map(unversion, params))
+
+    for rv in races:
+        if any(unversion(rv) == pv for pv in unver_params):
+            races1.discard(rv)
+        else:
+            break
+
+    return params | races1, races1
+
+
 def get_parfor_params_inner(parfor, pre_defs, options_fusion, fusion_info):
     blocks = wrap_parfor_blocks(parfor)
     cfg = compute_cfg_from_blocks(blocks)


Test patch:
diff --git a/numba/tests/test_parfors.py b/numba/tests/test_parfors.py
--- a/numba/tests/test_parfors.py
+++ b/numba/tests/test_parfors.py
@@ -3428,6 +3428,26 @@ def parallel_test(size, arr):
 
         self.check(parallel_test, size, arr)
 
+    @skip_parfors_unsupported
+    def test_issue5570_ssa_races(self):
+        @njit(parallel=True)
+        def foo(src, method, out):
+            for i in prange(1):
+                for j in range(1):
+                    out[i, j] = 1
+            if method:
+                out += 1
+            return out
+
+        src = np.zeros((5,5))
+        method = 57
+        out = np.zeros((2, 2))
+
+        self.assertPreciseEqual(
+            foo(src, method, out),
+            foo.py_func(src, method, out)
+        )
+
 
 @skip_parfors_unsupported
 class TestParforsDiagnostics(TestParforsBase):