def discover_args_and_returns(bytecode, insts, outer_rds, outer_wrs):
    rdnames, wrnames = find_varnames_uses(bytecode, insts)

    # Remove all local use from the set
    remove_from_outer_use(rdnames, outer_rds)
    remove_from_outer_use(wrnames, outer_wrs)

    # Return every variables that are written inside the loop and read
    # afterwards
    rets = set()
    for name, uselist in wrnames.items():
        if name in outer_rds:
            endofloop = insts[-1].offset

            # Find the next read
            for nextrd in outer_rds[name]:
                if nextrd > endofloop:
                    break
            else:
                nextrd = None

            # Find the next write
            for nextwr in outer_wrs[name]:
                if nextwr > endofloop:
                    break
            else:
                nextwr = None

            # If there is a read but no write OR
            # If the next use is a read, THEN
            # it is a return value
            if nextrd is not None and (nextwr is None or nextwr > nextrd):
                rets.add(name)

    # Make variables arguments if they are read before defined before the loop.
    # Since we can't tell if things are conditionally defined here,
    # We will have to be more conservative.
    args = set()
    firstline = insts[0].offset
    for name in rdnames.keys():
        outer_write = outer_wrs[name]
        # If there exists a definition before the start of the loop
        # for a variable read in side the loop.
        if any(i < firstline for i in outer_write):
            args.add(name)

    # Make variables arguments if it is being returned but defined before the
    # loop.
    for name in rets:
        if any(i < insts[0].offset for i in outer_wrs[name]):
            args.add(name)

    # Re-add the arguments back to outer_rds
    for name in args:
        outer_rds[name] = sorted(set(outer_rds[name]) | set([firstline]))

    # Re-add the arguments back to outer_wrs
    for name in rets:
        outer_wrs[name] = sorted(set(outer_wrs[name]) | set([firstline]))

    return args, rets
Basic analysis for args and returns
dataset/ETHPy150Open numba/numba/numba/looplifting.py/discover_args_and_returns