def fixup_var_define_in_scope(blocks):
    """Fixes the mapping of ir.Block to ensure all referenced ir.Var are
    defined in every scope used by the function. Such that looking up a variable
    from any scope in this function will not fail.

    Note: This is a workaround. Ideally, all the blocks should refer to the
    same ir.Scope, but that property is not maintained by all the passes.
    """
    # Scan for all used variables
    used_var = {}
    for blk in blocks.values():
        scope = blk.scope
        for inst in blk.body:
            for var in inst.list_vars():
                used_var[var] = inst
    # Note: not all blocks share a single scope even though they should.
    # Ensure the scope of each block defines all used variables.
    for blk in blocks.values():
        scope = blk.scope
        for var, inst in used_var.items():
            # add this variable if it's not in scope
            if var.name not in scope.localvars:
                # Note: using a internal method to reuse the same
                scope.localvars.define(var.name, var)
Fixes the mapping of ir.Block to ensure all referenced ir.Var are
    defined in every scope used by the function. Such that looking up a variable
    from any scope in this function will not fail.

    Note: This is a workaround. Ideally, all the blocks should refer to the
    same ir.Scope, but that property is not maintained by all the passes.
    
numba/core/ir_utils.py