-static void optimize_blocks(ir_node *b, void *env) {
- int i, j, k, n, max_preds, n_preds, p_preds;
- ir_node *pred, *phi;
- ir_node **in;
-
- /* Count the number of predecessor if this block is merged with pred blocks
- that are empty. */
- max_preds = 0;
- for (i = 0, k = get_Block_n_cfgpreds(b); i < k; ++i) {
- max_preds += test_whether_dispensable(b, i);
- }
- in = (ir_node **) malloc(max_preds * sizeof(ir_node *));
-
-/*-
- printf(" working on "); DDMN(b);
- for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
- pred = get_nodes_block(get_Block_cfgpred(b, i));
- if (is_Bad(get_Block_cfgpred(b, i))) {
- printf(" removing Bad %i\n ", i);
- } else if (get_Block_block_visited(pred) +1
- < get_irg_block_visited(current_ir_graph)) {
- printf(" removing pred %i ", i); DDMN(pred);
- } else { printf(" Nothing to do for "); DDMN(pred); }
- }
- * end Debug output -*/
-
- /*- Fix the Phi nodes of the current block -*/
- for (phi = get_irn_link(b); phi; ) {
- assert(get_irn_op(phi) == op_Phi);
-
- /* Find the new predecessors for the Phi */
- p_preds = 0;
- for (i = 0, n = get_Block_n_cfgpreds(b); i < n; ++i) {
- pred = get_nodes_block(get_Block_cfgpred(b, i));
-
- if (is_Bad(get_Block_cfgpred(b, i))) {
- /* case Phi 1: Do nothing */
- }
- else if (get_Block_block_visited(pred) + 1
- < get_irg_block_visited(current_ir_graph)) {
- /* case Phi 2: It's an empty block and not yet visited. */
- ir_node *phi_pred = get_Phi_pred(phi, i);
-
- for (j = 0, k = get_Block_n_cfgpreds(pred); j < k; j++) {
- /* because of breaking loops, not all predecessors are Bad-clean,
- * so we must check this here again */
- if (! is_Bad(get_Block_cfgpred(pred, j))) {
- if (get_nodes_block(phi_pred) == pred) {
- /* case Phi 2a: */
- assert(get_irn_op(phi_pred) == op_Phi); /* Block is empty!! */
-
- in[p_preds++] = get_Phi_pred(phi_pred, j);
- } else {
- /* case Phi 2b: */
- in[p_preds++] = phi_pred;
- }
- }
- }
-
- /* The Phi_pred node is replaced now if it is a Phi.
-
- Somehow the removed Phi node can be used legally in loops.
- Therefore we replace the old phi by the new one.
-
- Further we have to remove the old Phi node by replacing it
- by Bad. Else it will remain in the keepalive array of End
- and cause illegal situations. So if there is no loop, we should
- replace it by Bad.
- */
- if (get_nodes_block(phi_pred) == pred) {
- /* remove the Phi as it might be kept alive. Further there
- might be other users. */
- exchange(phi_pred, phi); /* geht, ist aber doch semantisch falsch! Warum?? */
- }
- } else {
- /* case Phi 3: */
- in[p_preds++] = get_Phi_pred(phi, i);
- }
- }
-
- /* Fix the node */
- if (p_preds == 1)
- /* By removal of Bad ins the Phi might be degenerated. */
- exchange(phi, in[0]);
- else
- set_irn_in(phi, p_preds, in);
-
- phi = get_irn_link(phi);
- }
-
- /*- This happens only if merge between loop backedge and single loop entry.
- See special case above. -*/
- for (k = 0, n = get_Block_n_cfgpreds(b); k < n; ++k) {
- pred = get_nodes_block(get_Block_cfgpred(b, k));
-
- if (get_Block_block_visited(pred) + 1 < get_irg_block_visited(current_ir_graph)) {
- /* we found a predecessor block at position k that will be removed */
- for (phi = get_irn_link(pred); phi;) {
- /*
- * the previous phase may already changed the phi, and even
- * removed it at all, so check here if this node is still a phi
- */
- if (get_irn_op(phi) == op_Phi) {
- int q_preds = 0;
-
- /* move this phi from the predecessor into the block b */
- set_nodes_block(phi, b);
-
- /* first, copy all 0..k-1 predecessors */
- for (i = 0; i < k; i++) {
- pred = get_nodes_block(get_Block_cfgpred(b, i));
-
- if (is_Bad(get_Block_cfgpred(b, i))) {
- /* Do nothing */
- } else if (get_Block_block_visited(pred) + 1
- < get_irg_block_visited(current_ir_graph)) {
- /* It's an empty block and not yet visited. */
- for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
- /* @@@ Hier brauche ich Schleifeninformation!!! Kontrollflusskante
- muss Rueckwaertskante sein! (An allen vier in[q_preds] = phi
- Anweisungen.) Trotzdem tuts bisher!! */
- if (! is_Bad(get_Block_cfgpred(pred, j)))
- in[q_preds++] = phi;
- }
- } else {
- in[q_preds++] = phi;
- }
- }
-
- /* now we are at k, copy the phi predecessors */
- pred = get_nodes_block(get_Block_cfgpred(b, k));
- for (i = 0; i < get_Phi_n_preds(phi); i++) {
- if (! is_Bad(get_Block_cfgpred(pred, i)))
- in[q_preds++] = get_Phi_pred(phi, i);
- }
-
- /* and now all the rest */
- for (i = k+1; i < get_Block_n_cfgpreds(b); i++) {
- pred = get_nodes_block(get_Block_cfgpred(b, i));
-
- if (is_Bad(get_Block_cfgpred(b, i))) {
- /* Do nothing */
- } else if (get_Block_block_visited(pred) +1
- < get_irg_block_visited(current_ir_graph)) {
- /* It's an empty block and not yet visited. */
- for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
- if (! is_Bad(get_Block_cfgpred(pred, j)))
- in[q_preds++] = phi;
- }
- } else {
- in[q_preds++] = phi;
- }
- }
-
- /* Fix the node */
- if (q_preds == 1)
- exchange(phi, in[0]);
- else
- set_irn_in(phi, q_preds, in);
-
-// assert(p_preds == q_preds && "Wrong Phi Fix");
- }
- phi = get_irn_link(phi);
- }
- }
- }
-
- /*- Fix the block -*/
- n_preds = 0;
- for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
- pred = get_nodes_block(get_Block_cfgpred(b, i));
-
- if (is_Bad(get_Block_cfgpred(b, i))) {
- /* case 1: Do nothing */
- } else if (get_Block_block_visited(pred) +1
- < get_irg_block_visited(current_ir_graph)) {
- /* case 2: It's an empty block and not yet visited. */
- assert(get_Block_n_cfgpreds(b) > 1);
- /* Else it should be optimized by equivalent_node. */
- for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
- ir_node *pred_block = get_Block_cfgpred(pred, j);
-
- /* because of breaking loops, not all predecessors are Bad-clean,
- * so we must check this here again */
- if (! is_Bad(pred_block))
- in[n_preds++] = pred_block;
- }
- /* Remove block as it might be kept alive. */
- exchange(pred, b/*new_Bad()*/);
- } else {
- /* case 3: */
- in[n_preds++] = get_Block_cfgpred(b, i);
- }
- }
- set_irn_in(b, n_preds, in);
-
- assert(get_irn_link(b) == NULL || (n_preds == p_preds && "Wrong Phi Fix"));
-
- free(in);
+static void optimize_blocks(ir_node *b, void *ctx)
+{
+ int i, j, k, n, max_preds, n_preds, p_preds = -1;
+ ir_node *pred, *phi, *next;
+ ir_node **in;
+ merge_env *env = ctx;
+
+ /* Count the number of predecessor if this block is merged with pred blocks
+ that are empty. */
+ max_preds = 0;
+ for (i = 0, k = get_Block_n_cfgpreds(b); i < k; ++i) {
+ max_preds += test_whether_dispensable(b, i);
+ }
+ in = XMALLOCN(ir_node*, max_preds);
+
+ /*- Fix the Phi nodes of the current block -*/
+ for (phi = get_irn_link(b); phi != NULL; phi = next) {
+ assert(is_Phi(phi));
+ next = get_irn_link(phi);
+
+ /* Find the new predecessors for the Phi */
+ p_preds = 0;
+ for (i = 0, n = get_Block_n_cfgpreds(b); i < n; ++i) {
+ pred = get_Block_cfgpred_block(b, i);
+
+ if (is_Block_dead(pred)) {
+ /* case Phi 1: Do nothing */
+ } else if (is_Block_removable(pred) && !Block_block_visited(pred)) {
+ /* case Phi 2: It's an empty block and not yet visited. */
+ ir_node *phi_pred = get_Phi_pred(phi, i);
+
+ for (j = 0, k = get_Block_n_cfgpreds(pred); j < k; j++) {
+ /* because of breaking loops, not all predecessors are Bad-clean,
+ * so we must check this here again */
+ if (! is_Bad(get_Block_cfgpred(pred, j))) {
+ if (get_nodes_block(phi_pred) == pred) {
+ /* case Phi 2a: */
+ assert(is_Phi(phi_pred)); /* Block is empty!! */
+
+ in[p_preds++] = get_Phi_pred(phi_pred, j);
+ } else {
+ /* case Phi 2b: */
+ in[p_preds++] = phi_pred;
+ }
+ }
+ }
+ } else {
+ /* case Phi 3: */
+ in[p_preds++] = get_Phi_pred(phi, i);
+ }
+ }
+ assert(p_preds <= max_preds);
+
+ /* Fix the node */
+ if (p_preds == 1)
+ /* By removal of Bad ins the Phi might be degenerated. */
+ exchange(phi, in[0]);
+ else
+ set_irn_in(phi, p_preds, in);
+ env->changed = 1;
+ }
+
+ /*- This happens only if merge between loop backedge and single loop entry.
+ Moreover, it is only needed if predb is the direct dominator of b, else there can be no uses
+ of the Phi's in predb ... -*/
+ for (k = 0, n = get_Block_n_cfgpreds(b); k < n; ++k) {
+ ir_node *predb = get_nodes_block(get_Block_cfgpred(b, k));
+
+ if (is_Block_removable(predb) && !Block_block_visited(predb)) {
+ ir_node *next_phi;
+
+ /* we found a predecessor block at position k that will be removed */
+ for (phi = get_irn_link(predb); phi; phi = next_phi) {
+ int q_preds = 0;
+ next_phi = get_irn_link(phi);
+
+ assert(is_Phi(phi));
+
+ if (get_Block_idom(b) != predb) {
+ /* predb is not the dominator. There can't be uses of pred's Phi nodes, kill them .*/
+ exchange(phi, new_Bad());
+ } else {
+ /* predb is the direct dominator of b. There might be uses of the Phi nodes from
+ predb in further block, so move this phi from the predecessor into the block b */
+ set_nodes_block(phi, b);
+ set_irn_link(phi, get_irn_link(b));
+ set_irn_link(b, phi);
+ env->phis_moved = 1;
+
+ /* first, copy all 0..k-1 predecessors */
+ for (i = 0; i < k; i++) {
+ pred = get_Block_cfgpred_block(b, i);
+
+ if (is_Block_dead(pred)) {
+ /* Do nothing */
+ } else if (is_Block_removable(pred) && !Block_block_visited(pred)) {
+ /* It's an empty block and not yet visited. */
+ for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
+ if (! is_Bad(get_Block_cfgpred(pred, j)))
+ in[q_preds++] = phi;
+ }
+ } else {
+ in[q_preds++] = phi;
+ }
+ }
+
+ /* now we are at k, copy the phi predecessors */
+ pred = get_nodes_block(get_Block_cfgpred(b, k));
+ for (i = 0; i < get_Phi_n_preds(phi); i++) {
+ if (! is_Bad(get_Block_cfgpred(pred, i)))
+ in[q_preds++] = get_Phi_pred(phi, i);
+ }
+
+ /* and now all the rest */
+ for (i = k+1; i < get_Block_n_cfgpreds(b); i++) {
+ pred = get_Block_cfgpred_block(b, i);
+
+ if (is_Block_dead(pred)) {
+ /* Do nothing */
+ } else if (is_Block_removable(pred) && !Block_block_visited(pred)) {
+ /* It's an empty block and not yet visited. */
+ for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
+ if (! is_Bad(get_Block_cfgpred(pred, j)))
+ in[q_preds++] = phi;
+ }
+ } else {
+ in[q_preds++] = phi;
+ }
+ }
+
+ /* Fix the node */
+ if (q_preds == 1)
+ exchange(phi, in[0]);
+ else
+ set_irn_in(phi, q_preds, in);
+ env->changed = 1;
+
+ assert(q_preds <= max_preds);
+ // assert(p_preds == q_preds && "Wrong Phi Fix");
+ }
+ }
+ }
+ }
+
+ /*- Fix the block -*/
+ n_preds = 0;
+ for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
+ pred = get_Block_cfgpred_block(b, i);
+
+ if (is_Block_dead(pred)) {
+ /* case 1: Do nothing */
+ } else if (is_Block_removable(pred) && !Block_block_visited(pred)) {
+ /* case 2: It's an empty block and not yet visited. */
+ assert(get_Block_n_cfgpreds(b) > 1 || has_Block_entity(b));
+ /* Else it should be optimized by equivalent_node. */
+ for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
+ ir_node *pred_X = get_Block_cfgpred(pred, j);
+
+ /* because of breaking loops, not all predecessors are Bad-clean,
+ * so we must check this here again */
+ if (! is_Bad(pred_X))
+ in[n_preds++] = pred_X;
+ }
+ /* Remove block as it might be kept alive. */
+ exchange(pred, b/*new_Bad()*/);
+ } else {
+ /* case 3: */
+ in[n_preds++] = get_Block_cfgpred(b, i);
+ }
+ }
+ assert(n_preds <= max_preds);
+
+ set_irn_in(b, n_preds, in);
+ env->changed = 1;
+
+ assert(get_irn_link(b) == NULL || p_preds == -1 || (n_preds == p_preds && "Wrong Phi Fix"));
+ xfree(in);