2 * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
6 * This file may be distributed and/or modified under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation and appearing in the file LICENSE.GPL included in the
9 * packaging of this file.
11 * Licensees holding valid libFirm Professional Edition licenses may use
12 * this file in accordance with the libFirm Commercial License.
13 * Agreement provided with the Software.
15 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * @brief Remove critical edges.
23 * @author Christian Schaefer, Goetz Lindenmaier, Sebastian Felis,
37 typedef struct cf_env {
38 char ignore_exc_edges; /**< set if exception edges should be ignored. */
39 char changed; /**< flag indicates that the cf graphs has changed. */
43 * Called by walker of remove_critical_cf_edges().
45 * Place an empty block to an edge between a blocks of multiple
46 * predecessors and a block of multiple successors.
49 * @param env Environment of walker.
51 static void walk_critical_cf_edges(ir_node *n, void *env) {
53 ir_node *pre, *block, *jmp;
55 ir_graph *irg = get_irn_irg(n);
57 /* Block has multiple predecessors */
58 arity = get_irn_arity(n);
60 if (n == get_irg_end_block(irg))
61 return; /* No use to add a block here. */
63 for (i = 0; i < arity; ++i) {
66 pre = get_irn_n(n, i);
67 /* don't count Bad's */
71 cfop = get_irn_op(skip_Proj(pre));
72 if (is_op_fragile(cfop)) {
73 if (cenv->ignore_exc_edges && get_Proj_proj(pre) == pn_Generic_X_except)
77 /* we don't want place nodes in the start block, so handle it like forking */
78 if (is_op_forking(cfop) || cfop == op_Start) {
79 /* Predecessor has multiple successors. Insert new control flow edge edges. */
81 /* set predecessor of new block */
82 block = new_r_Block(irg, 1, &pre);
83 /* insert new jmp node to new block */
84 jmp = new_r_Jmp(irg, block);
85 /* set successor of new block */
88 } /* predecessor has multiple successors */
89 } /* for all predecessors */
90 } /* n is a multi-entry block */
93 void remove_critical_cf_edges_ex(ir_graph *irg, int ignore_exception_edges) {
96 env.ignore_exc_edges = (char)ignore_exception_edges;
99 irg_block_walk_graph(irg, NULL, walk_critical_cf_edges, &env);
101 /* control flow changed */
102 set_irg_outs_inconsistent(irg);
103 set_irg_extblk_inconsistent(irg);
104 set_irg_doms_inconsistent(irg);
105 set_irg_loopinfo_inconsistent(irg);
109 void remove_critical_cf_edges(ir_graph *irg) {
110 remove_critical_cf_edges_ex(irg, 1);