Simplify the CFG by merging/deleting statement nodes when possible:
    If statement B follows statement A and if B has no other predecessor
    besides A, then we can merge A and B into a new statement node.
    We also remove nodes which do nothing except redirecting the control
    flow (nodes which only contains a goto).

def simplify(graph):
    """
    Simplify the CFG by merging/deleting statement nodes when possible:
    If statement B follows statement A and if B has no other predecessor
    besides A, then we can merge A and B into a new statement node.
    We also remove nodes which do nothing except redirecting the control
    flow (nodes which only contains a goto).
    """
    redo = True
    while redo:
        redo = False
        node_map = {}
        to_update = set()
        for node in graph.nodes[:]:
            if node.type.is_stmt and node in graph:
                sucs = graph.all_sucs(node)
                if len(sucs) != 1:
                    continue
                suc = sucs[0]
                if len(node.get_ins()) == 0:
                    if any(pred.type.is_switch
                           for pred in graph.all_preds(node)):
                        continue
                    if node is suc:
                        continue
                    node_map[node] = suc

                    for pred in graph.all_preds(node):
                        pred.update_attribute_with(node_map)
                        if node not in graph.sucs(pred):
                            graph.add_catch_edge(pred, suc)
                            continue
                        graph.add_edge(pred, suc)
                    redo = True
                    if node is graph.entry:
                        graph.entry = suc
                    graph.remove_node(node)
                elif (suc.type.is_stmt and len(graph.all_preds(suc)) == 1 and
                          not (suc in graph.catch_edges) and not (
                            (node is suc) or (suc is graph.entry))):
                    ins_to_merge = suc.get_ins()
                    node.add_ins(ins_to_merge)
                    for var in suc.var_to_declare:
                        node.add_variable_declaration(var)
                    new_suc = graph.sucs(suc)[0]
                    if new_suc:
                        graph.add_edge(node, new_suc)
                    for exception_suc in graph.catch_edges.get(suc, []):
                        graph.add_catch_edge(node, exception_suc)
                    redo = True
                    graph.remove_node(suc)
            else:
                to_update.add(node)
        for node in to_update:
            node.update_attribute_with(node_map)