# Buggy code
def run(self):
    """Finds all calls to StencilFuncs in the IR and converts them to parfor."""
    from numba.stencil import StencilFunc

    # Get all the calls in the function IR.
    call_table, _ = get_call_table(self.func_ir.blocks)
    stencil_calls = []
    stencil_dict = {}
    for call_varname, call_list in call_table.items():
        if isinstance(call_list[0], StencilFunc):
            # Remember all calls to StencilFuncs.
            stencil_calls.append(call_varname)
            stencil_dict[call_varname] = call_list[0]
    if not stencil_calls:
        return  # return early if no stencil calls found

    # find and transform stencil calls
    for label, block in self.func_ir.blocks.items():
        for i, stmt in reversed(list(enumerate(block.body))):
            # Found a call to a StencilFunc.
            if (
                isinstance(stmt, ir.Assign)
                and isinstance(stmt.value, ir.Expr)
                and stmt.value.op == "call"
                and stmt.value.func.name in stencil_calls
            ):
                kws = dict(stmt.value.kws)
                # Create dictionary of input argument number to
                # the argument itself.
                input_dict = {
                    i: stmt.value.args[i] for i in range(len(stmt.value.args))
                }
                in_args = stmt.value.args
                arg_typemap = tuple(self.typemap[i.name] for i in in_args)
                for arg_type in arg_typemap:
                    if isinstance(arg_type, types.BaseTuple):
                        raise ValueError(
                            "Tuple parameters not supported "
                            "for stencil kernels in parallel=True mode."
                        )

                out_arr = kws.get("out")

                # Get the StencilFunc object corresponding to this call.
                sf = stencil_dict[stmt.value.func.name]
                stencil_blocks, rt, arg_to_arr_dict = get_stencil_blocks(
                    sf,
                    self.typingctx,
                    arg_typemap,
                    block.scope,
                    block.loc,
                    input_dict,
                    self.typemap,
                    self.calltypes,
                )
                index_offsets = sf.options.get("index_offsets", None)
                gen_nodes = self._mk_stencil_parfor(
                    label,
                    in_args,
                    out_arr,
                    stencil_blocks,
                    index_offsets,
                    stmt.target,
                    rt,
                    sf,
                    arg_to_arr_dict,
                )
                block.body = block.body[:i] + gen_nodes + block.body[i + 1 :]
            # Found a call to a stencil via numba.stencil().
            elif (
                isinstance(stmt, ir.Assign)
                and isinstance(stmt.value, ir.Expr)
                and stmt.value.op == "call"
                and guard(find_callname, self.func_ir, stmt.value)
                == ("stencil", "numba")
            ):
                # remove dummy stencil() call
                stmt.value = ir.Const(0, stmt.loc)


# Traceback (LoweringError)
Serial:
[ 0  1  2  3  4 15 16 17 18 19]

Parallel:
Parallel for-loop #0 is produced from pattern '('prange', 'user')' at <ipython-input-1-f9ca7dd40116> (18)
After fusion, function parallel has 1 parallel for-loop(s) #set([0]).

---------------------------------------------------------------------------
LoweringError                             Traceback (most recent call last)
<ipython-input-1-f9ca7dd40116> in <module>()
27 print('\nParallel:')
28 A = np.arange(10)
---> 29 parallel(A)
30 print(A)

/home/lgarrison/anaconda2/lib/python2.7/site-packages/numba/dispatcher.pyc in _compile_for_args(self, *args, **kws)
358                     e.patch_message(''.join(e.args) + help_msg)
359             # ignore the FULL_TRACEBACKS config, this needs reporting!
--> 360             raise e
361
362     def inspect_llvm(self, signature=None):

LoweringError: Failed at nopython (nopython mode backend)
Failed at nopython (nopython mode backend)
expecting {{i8*, i8*, i64, i64, i64*, [1 x i64], [1 x i64]}, i64, i64*} but got i8*

File "<ipython-input-1-f9ca7dd40116>", line 18:
def parallel(A):
<source elided>
N = len(A)
for i in numba.prange(N):
^
[1] During: lowering "id=0[LoopNest(index_variable = parfor_index.2, range = (0, $N.4, 1))]{40: <ir.Block at <ipython-input-1-f9ca7dd40116> (18)>, 81: <ir.Block at <ipython-input-1-f9ca7dd40116> (18)>, 59: <ir.Block at <ipython-input-1-f9ca7dd40116> (19)>}Var(parfor_index.2, <ipython-input-1-f9ca7dd40116> (18))" at <ipython-input-1-f9ca7dd40116> (18)
-------------------------------------------------------------------------------
This should not have happened, a problem has occurred in Numba's internals.

Please report the error message and traceback, along with a minimal reproducer
at: https://github.com/numba/numba/issues/new

If you need help writing a minimal reproducer please see:
http://matthewrocklin.com/blog/work/2018/02/28/minimal-bug-reports

If more help is needed please feel free to speak to the Numba core developers
directly at: https://gitter.im/numba/numba

Thanks in advance for your help in improving Numba!

# Fixed code
def run(self):
    """Finds all calls to StencilFuncs in the IR and converts them to parfor."""
    from numba.stencil import StencilFunc

    # Get all the calls in the function IR.
    call_table, _ = get_call_table(self.func_ir.blocks)
    stencil_calls = []
    stencil_dict = {}
    for call_varname, call_list in call_table.items():
        if isinstance(call_list[0], StencilFunc):
            # Remember all calls to StencilFuncs.
            stencil_calls.append(call_varname)
            stencil_dict[call_varname] = call_list[0]
    if not stencil_calls:
        return  # return early if no stencil calls found

    # find and transform stencil calls
    for label, block in self.func_ir.blocks.items():
        for i, stmt in reversed(list(enumerate(block.body))):
            # Found a call to a StencilFunc.
            if (
                isinstance(stmt, ir.Assign)
                and isinstance(stmt.value, ir.Expr)
                and stmt.value.op == "call"
                and stmt.value.func.name in stencil_calls
            ):
                kws = dict(stmt.value.kws)
                # Create dictionary of input argument number to
                # the argument itself.
                input_dict = {
                    i: stmt.value.args[i] for i in range(len(stmt.value.args))
                }
                in_args = stmt.value.args
                arg_typemap = tuple(self.typemap[i.name] for i in in_args)
                for arg_type in arg_typemap:
                    if isinstance(arg_type, types.BaseTuple):
                        raise ValueError(
                            "Tuple parameters not supported "
                            "for stencil kernels in parallel=True mode."
                        )

                out_arr = kws.get("out")

                # Get the StencilFunc object corresponding to this call.
                sf = stencil_dict[stmt.value.func.name]
                stencil_ir, rt, arg_to_arr_dict = get_stencil_ir(
                    sf,
                    self.typingctx,
                    arg_typemap,
                    block.scope,
                    block.loc,
                    input_dict,
                    self.typemap,
                    self.calltypes,
                )
                index_offsets = sf.options.get("index_offsets", None)
                gen_nodes = self._mk_stencil_parfor(
                    label,
                    in_args,
                    out_arr,
                    stencil_ir,
                    index_offsets,
                    stmt.target,
                    rt,
                    sf,
                    arg_to_arr_dict,
                )
                block.body = block.body[:i] + gen_nodes + block.body[i + 1 :]
            # Found a call to a stencil via numba.stencil().
            elif (
                isinstance(stmt, ir.Assign)
                and isinstance(stmt.value, ir.Expr)
                and stmt.value.op == "call"
                and guard(find_callname, self.func_ir, stmt.value)
                == ("stencil", "numba")
            ):
                # remove dummy stencil() call
                stmt.value = ir.Const(0, stmt.loc)