+
+
+/**
+ * Called by walker of remove_critical_cf_edges.
+ *
+ * Place an empty block to an edge between a blocks of multiple
+ * predecessors and a block of multiple sucessors.
+ *
+ * @param n IR node
+ * @param env Envirnment of walker. This field is unused and has
+ * the value NULL.
+ */
+static void walk_critical_cf_edges(ir_node *n, void *env) {
+ int arity, i;
+ ir_node *pre, *block, **in, *jmp;
+
+ /* Block has multiple predecessors */
+ if ((op_Block == get_irn_op(n)) &&
+ (get_irn_arity(n) > 1)) {
+ arity = get_irn_arity(n);
+
+ for (i=0; i<arity; i++) {
+ pre = get_irn_n(n, i);
+ /* Predecessor has multiple sucessors. Insert new flow edge */
+ if ((NULL != pre) && (op_Proj == get_irn_op(pre))) {
+
+ /* set predecessor array for new block */
+ in = NEW_ARR_D (ir_node *, current_ir_graph->obst, 1);
+ /* set predecessor of new block */
+ in[0] = pre;
+ block = new_Block(1, in);
+ /* insert new jmp node to new block */
+ switch_block(block);
+ jmp = new_Jmp();
+ switch_block(n);
+ /* set sucessor of new block */
+ set_irn_n(n, i, jmp);
+
+ } /* predecessor has multiple sucessors */
+ } /* for all predecessors */
+ } /* n is a block */
+}
+
+void remove_critical_cf_edges(ir_graph *irg) {
+ if (get_opt_critical_edges())
+ irg_walk_graph(irg, NULL, walk_critical_cf_edges, NULL);
+}