2 * This file is part of libFirm.
3 * Copyright (C) 2012 University of Karlsruhe.
8 * @brief Remove critical edges.
9 * @author Christian Schaefer, Goetz Lindenmaier, Sebastian Felis,
20 typedef struct cf_env {
21 char ignore_exc_edges; /**< set if exception edges should be ignored. */
22 char changed; /**< flag indicates that the cf graphs has changed. */
26 * Called by walker of remove_critical_cf_edges().
28 * Place an empty block to an edge between a blocks of multiple
29 * predecessors and a block of multiple successors.
32 * @param env Environment of walker.
34 static void walk_critical_cf_edges(ir_node *n, void *env)
37 ir_node *pre, *block, *jmp;
38 cf_env *cenv = (cf_env*)env;
39 ir_graph *irg = get_irn_irg(n);
41 /* Block has multiple predecessors */
42 arity = get_irn_arity(n);
44 if (n == get_irg_end_block(irg))
45 return; /* No use to add a block here. */
47 for (i = 0; i < arity; ++i) {
50 pre = get_irn_n(n, i);
51 /* don't count Bad's */
55 cfop = get_irn_op(skip_Proj(pre));
56 if (is_op_fragile(cfop)) {
57 if (cenv->ignore_exc_edges && is_x_except_Proj(pre))
61 if (is_unknown_jump(pre)) {
62 /* we can't add blocks in between ijmp and its destinations
63 * TODO: What now, we can't split all critical edges because of this... */
64 fprintf(stderr, "libfirm warning: Couldn't split all critical edges (compiler will probably fail now)\n");
67 /* we don't want place nodes in the start block, so handle it like forking */
68 if (is_op_forking(cfop) || cfop == op_Start) {
69 /* Predecessor has multiple successors. Insert new control flow edge edges. */
71 /* set predecessor of new block */
72 block = new_r_Block(irg, 1, &pre);
73 /* insert new jmp node to new block */
74 jmp = new_r_Jmp(block);
75 /* set successor of new block */
83 void remove_critical_cf_edges_ex(ir_graph *irg, int ignore_exception_edges)
87 env.ignore_exc_edges = (char)ignore_exception_edges;
90 irg_block_walk_graph(irg, NULL, walk_critical_cf_edges, &env);
92 /* control flow changed */
93 clear_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_DOMINANCE);
95 add_irg_properties(irg, IR_GRAPH_PROPERTY_NO_CRITICAL_EDGES);
98 void remove_critical_cf_edges(ir_graph *irg)
100 remove_critical_cf_edges_ex(irg, 1);