def rename_labels(blocks):
    """rename labels of function body blocks according to topological sort.
    The set of labels of these blocks will remain unchanged.
    """
    topo_order = find_topo_order(blocks)

    # make a block with return last if available (just for readability)
    return_label = -1
    for l, b in blocks.items():
        if isinstance(b.body[-1], ir.Return):
            return_label = l
    # some cases like generators can have no return blocks
    if return_label != -1:
        topo_order.remove(return_label)
        topo_order.append(return_label)

    label_map = {}
    all_labels = sorted(topo_order, reverse=True)
    for label in topo_order:
        label_map[label] = all_labels.pop()
    # update target labels in jumps/branches
    for b in blocks.values():
        term = b.terminator
        # create new IR nodes instead of mutating the existing one as copies of
        # the IR may also refer to the same nodes!
        if isinstance(term, ir.Jump):
            b.body[-1] = ir.Jump(label_map[term.target], term.loc)
        if isinstance(term, ir.Branch):
            b.body[-1] = ir.Branch(term.cond,
                                   label_map[term.truebr],
                                   label_map[term.falsebr],
                                   term.loc)



    # update blocks dictionary keys
    new_blocks = {}
    for k, b in blocks.items():
        new_label = label_map[k]
        new_blocks[new_label] = b

    return new_blocks
rename labels of function body blocks according to topological sort.
    The set of labels of these blocks will remain unchanged.
    
numba/core/ir_utils.py