- int i;
- ir_node *orig_block = get_nodes_block(orig);
- ir_graph *irg = get_irn_irg(orig);
- ir_mode *mode = get_irn_mode(orig);
- pdeq *worklist = new_pdeq();
- pset *phi_blocks = pset_new_ptr(8);
- ir_node **ins = NULL;
- void *it;
-
- /*
- * Allocate an array for all blocks where the copies and the original
- * value were defined.
- */
- int n_orig_blocks = pset_count(copy_blocks) + 1;
- ir_node **orig_blocks = malloc(n_orig_blocks * sizeof(orig_blocks[0]));
-
- /*
- * Fill the array of definition blocks.
- */
- orig_blocks[0] = get_nodes_block(orig);
-
- /*
- * Fill the worklist queue and the rest of the orig blocks array.
- */
- for(it = pset_first(copies), i = 1; it; it = pset_next(copies)) {
- ir_node *copy_block = get_nodes_block(it);
-
- assert(block_dominates(orig_block, copy_block)
- && "The block of the copy must be dominated by the block of the value");
-
- pdeq_putr(worklist, it);
- orig_blocks[i++] = copy_block;
- }
-
- while(!pdeq_empty(worklist)) {
- ir_node *irn = pdeq_getl(worklist);
- ir_node *bl = get_nodes_block(irn);
- ir_node *y;
- int n_preds = get_irn_arity(bl);
- pset *df = be_get_dominance_frontier(df_info, bl);
-
- for(y = pset_first(df); y; y = pset_next(df)) {
-
- if(!pset_find_ptr(phi_blocks, y)) {
- ir_node *phi;
- int insert = 1;
-
- /*
- * Set the orig node as the only operand of the
- * phi node.
- */
- ins = realloc(ins, n_preds * sizeof(ins[0]));
- for(i = 0; i < n_preds; ++i)
- ins[0] = orig;
-
- /* Insert phi node */
- phi = new_r_Phi(irg, bl, n_preds, ins, mode);
-
- /*
- * The phi node itself is also a copy of the original
- * value. So put it in the copies set also, so that
- * the rename phase can treat them right.
- */
- pset_insert_ptr(copies, phi);
- pset_insert_ptr(copy_blocks, y);
-
- /* Insert the phi node into the schedule */
- sched_add_before(sched_first(y), phi);
-
- /* Insert the phi node in the phi blocks set. */
- pset_insert_ptr(phi_blocks, y);
-
- /*
- * If orig or a copy of it were not defined in y,
- * add y to the worklist.
- */
- for(i = 0; i < n_orig_blocks; ++i)
- if(orig_blocks[i] == y) {
- insert = 0;
- break;
- }
-
- if(insert)
- pdeq_putr(worklist, y);
-
- }
- }
- }
-
- del_pset(phi_blocks);
- del_pdeq(worklist);
-
- free(orig_blocks);
-
- if(ins)
- free(ins);
+ const ir_edge_t *edge, *next;
+ int i, arity;
+ ir_node *node;
+ ir_node *pred;
+ ir_node *succ_block;
+ ir_node *jump = NULL;
+
+ if (irn_visited_else_mark(block))
+ return;
+
+ if (get_Block_n_cfgpreds(block) != 1)
+ goto check_preds;
+
+ sched_foreach(block, node) {
+ if (! is_Jmp(node))
+ goto check_preds;
+ if (jump != NULL) {
+ /* we should never have 2 jumps in a block */
+ panic("found 2 jumps in a block");
+ }
+ jump = node;
+ }
+
+ if (jump == NULL)
+ goto check_preds;
+
+ pred = get_Block_cfgpred(block, 0);
+ succ_block = NULL;
+ foreach_out_edge_safe(jump, edge, next) {
+ int pos = get_edge_src_pos(edge);
+
+ assert(succ_block == NULL);
+ succ_block = get_edge_src_irn(edge);
+
+ set_irn_n(succ_block, pos, pred);
+ }
+
+ /* there can be some non-scheduled Pin nodes left in the block, move them
+ * to the succ block (Pin) or pred block (Sync) */
+ foreach_out_edge_safe(block, edge, next) {
+ node = get_edge_src_irn(edge);
+
+ if(node == jump)
+ continue;
+ if (is_Block(node)) {
+ /* a Block->Block edge: This should be the MacroBlock
+ edge, ignore it. */
+ assert(get_Block_MacroBlock(node) == block && "Wrong Block->Block edge");
+ continue;
+ }
+ if (is_Pin(node)) {
+ set_nodes_block(node, succ_block);
+ continue;
+ }
+ if (is_Sync(node)) {
+ set_nodes_block(node, get_nodes_block(pred));
+ continue;
+ }
+ if (is_End(node)) { /* End-keep, reroute it to the successor */
+ int pos = get_edge_src_pos(edge);
+ set_irn_n(node, pos, succ_block);
+ continue;
+ }
+ panic("Unexpected node %+F in block %+F with empty schedule", node, block);
+ }
+
+ set_Block_cfgpred(block, 0, new_Bad());
+ kill_node(jump);
+ blocks_removed = 1;
+
+ /* check predecessor */
+ remove_empty_block(get_nodes_block(pred));
+ return;
+
+check_preds:
+ arity = get_Block_n_cfgpreds(block);
+ for(i = 0; i < arity; ++i) {
+ ir_node *pred = get_Block_cfgpred_block(block, i);
+ remove_empty_block(pred);
+ }