#include "irop.h"
#include "irouts.h"
#include "irgmod.h"
+#include "iropt_dbg.h"
#include "debug.h"
#include "error.h"
/* define this to check the consistency of partitions */
#define CHECK_PARTITIONS
-/* define this to disable followers (may be buggy) */
-#undef NO_FOLLOWER
-
typedef struct node_t node_t;
typedef struct partition_t partition_t;
typedef struct opcode_key_t opcode_key_t;
return Z_prime;
} /* split_no_followers */
-#ifdef NO_FOLLOWER
-
-#define split(Z, g, env) split_no_followers(*(Z), g, env)
-
-#else
-
/**
* Make the Follower -> Leader transition for a node.
*
return X_prime;
} /* split */
-#endif /* NO_FOLLOWER */
/**
* Returns non-zero if the i'th input of a Phi node is live.
* NaN != NaN is defined, so we must check this here.
*/
tv = new_tarval_from_long(pnc & pn_Cmp_Eq, mode_b);
+#ifdef WITH_UNKNOWN
not_equal:
+#endif
/* if the node was ONCE evaluated by all constants, but now
this breakes AND we cat by partition a different result, switch to bottom.
for (x = fallen; x != NULL; x = x->next)
x->on_fallen = 0;
-#ifndef NO_FOLLOWER
if (old_type_was_T_or_C) {
node_t *y, *tmp;
}
}
}
-#endif
split_by(Y, env);
}
} /* propagate */
return 1;
}
return 0;
-}
+} /* can_exchange */
/**
* Block Post-Walker, apply the analysis results on control flow by
ir_node **ins, **in_X;
ir_node *phi, *next;
- if (block == get_irg_end_block(current_ir_graph) ||
- block == get_irg_start_block(current_ir_graph)) {
+ n = get_Block_n_cfgpreds(block);
+
+ if (node->type.tv == tarval_unreachable) {
+ env->modified = 1;
+
+ for (i = n - 1; i >= 0; --i) {
+ ir_node *pred = get_Block_cfgpred(block, i);
+
+ if (! is_Bad(pred)) {
+ node_t *pred_bl = get_irn_node(get_nodes_block(skip_Proj(pred)));
+
+ if (pred_bl->flagged == 0) {
+ pred_bl->flagged = 3;
+
+ if (pred_bl->type.tv == tarval_reachable) {
+ /*
+ * We will remove an edge from block to its pred.
+ * This might leave the pred block as an endless loop
+ */
+ if (! is_backedge(block, i))
+ keep_alive(pred_bl->node);
+ }
+ }
+ }
+ }
+
/* the EndBlock is always reachable even if the analysis
finds out the opposite :-) */
+ if (block != get_irg_end_block(current_ir_graph)) {
+ /* mark dead blocks */
+ set_Block_dead(block);
+ DB((dbg, LEVEL_1, "Removing dead %+F\n", block));
+ } else {
+ /* the endblock is unreachable */
+ set_irn_in(block, 0, NULL);
+ }
return;
}
- if (node->type.tv == tarval_unreachable) {
- /* mark dead blocks */
- set_Block_dead(block);
- return;
- }
-
- n = get_Block_n_cfgpreds(block);
if (n == 1) {
/* only one predecessor combine */
ir_node *pred = skip_Proj(get_Block_cfgpred(block, 0));
if (can_exchange(pred)) {
- exchange(block, get_nodes_block(pred));
+ ir_node *new_block = get_nodes_block(pred);
+ DB((dbg, LEVEL_1, "Fuse %+F with %+F\n", block, new_block));
+ DBG_OPT_COMBO(block, new_block, FS_OPT_COMBO_CF);
+ exchange(block, new_block);
+ node->node = new_block;
env->modified = 1;
}
return;
if (node->type.tv == tarval_reachable) {
in_X[k++] = pred;
+ } else {
+ DB((dbg, LEVEL_1, "Removing dead input %d from %+F (%+F)\n", i, block, pred));
+ if (! is_Bad(pred)) {
+ node_t *pred_bl = get_irn_node(get_nodes_block(skip_Proj(pred)));
+
+ if (pred_bl->flagged == 0) {
+ pred_bl->flagged = 3;
+
+ if (pred_bl->type.tv == tarval_reachable) {
+ /*
+ * We will remove an edge from block to its pred.
+ * This might leave the pred block as an endless loop
+ */
+ if (! is_backedge(block, i))
+ keep_alive(pred_bl->node);
+ }
+ }
+ }
}
}
if (k >= n)
set_irn_node(c, node);
node->node = c;
DB((dbg, LEVEL_1, "%+F is replaced by %+F\n", phi, c));
+ DBG_OPT_COMBO(phi, c, FS_OPT_COMBO_CONST);
exchange(phi, c);
env->modified = 1;
} else {
ins[j++] = get_Phi_pred(phi, i);
}
}
- if (j <= 1) {
+ if (j == 1) {
/* this Phi is replaced by a single predecessor */
ir_node *s = ins[0];
+ node_t *phi_node = get_irn_node(phi);
node->node = s;
DB((dbg, LEVEL_1, "%+F is replaced by %+F because of cf change\n", phi, s));
+ DBG_OPT_COMBO(phi, s, FS_OPT_COMBO_FOLLOWER);
exchange(phi, s);
+ phi_node->node = s;
env->modified = 1;
} else {
set_irn_in(phi, j, ins);
}
}
- if (k <= 1) {
+ if (k == 1) {
/* this Block has only one live predecessor */
ir_node *pred = skip_Proj(in_X[0]);
if (can_exchange(pred)) {
- exchange(block, get_nodes_block(pred));
+ ir_node *new_block = get_nodes_block(pred);
+ DBG_OPT_COMBO(block, new_block, FS_OPT_COMBO_CF);
+ exchange(block, new_block);
+ node->node = new_block;
env->modified = 1;
}
} else {
node_t *sel = get_irn_node(get_Cond_selector(cond));
if (is_tarval(sel->type.tv) && tarval_is_constant(sel->type.tv)) {
- /* Cond selector is a constant, make a Jmp */
- ir_node *jmp = new_r_Jmp(current_ir_graph, block->node);
+ /* Cond selector is a constant and the Proj is reachable, make a Jmp */
+ ir_node *jmp = new_r_Jmp(current_ir_graph, block->node);
set_irn_node(jmp, node);
node->node = jmp;
DB((dbg, LEVEL_1, "%+F is replaced by %+F\n", irn, jmp));
+ DBG_OPT_COMBO(irn, jmp, FS_OPT_COMBO_CF);
exchange(irn, jmp);
env->modified = 1;
}
set_irn_node(c, node);
node->node = c;
DB((dbg, LEVEL_1, "%+F is replaced by %+F\n", irn, c));
+ DBG_OPT_COMBO(irn, c, FS_OPT_COMBO_CONST);
exchange(irn, c);
env->modified = 1;
}
node->node = symc;
DB((dbg, LEVEL_1, "%+F is replaced by %+F\n", irn, symc));
+ DBG_OPT_COMBO(irn, symc, FS_OPT_COMBO_CONST);
exchange(irn, symc);
env->modified = 1;
}
if (leader != irn) {
DB((dbg, LEVEL_1, "%+F from part%d is replaced by %+F\n", irn, node->part->nr, leader));
+ if (node->is_follower)
+ DBG_OPT_COMBO(irn, leader, FS_OPT_COMBO_FOLLOWER);
+ else
+ DBG_OPT_COMBO(irn, leader, FS_OPT_COMBO_CONGRUENT);
exchange(irn, leader);
env->modified = 1;
}
ir_node *ka = get_End_keepalive(end, i);
node_t *node = get_irn_node(ka);
- /* Use the flagged bits to mark already visited nodes.
- * This should not be ready but better safe than sorry. */
- if (node->flagged == 0) {
- node->flagged = 3;
+ if (! is_Block(ka))
+ node = get_irn_node(get_nodes_block(ka));
- if (! is_Block(ka))
- node = get_irn_node(get_nodes_block(ka));
-
- if (node->type.tv != tarval_unreachable)
- in[j++] = ka;
- }
+ if (node->type.tv != tarval_unreachable)
+ in[j++] = ka;
}
if (j != n) {
set_End_keepalives(end, j, in);
env.modified = 0;
assure_irg_outs(irg);
+ assure_cf_loop(irg);
+
/* we have our own value_of function */
set_value_of_func(get_node_tarval);
set_compute_functions();
DEBUG_ONLY(part_nr = 0);
+ ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK);
+
/* create the initial partition and place it on the work list */
env.initial = new_partition(&env);
add_to_worklist(env.initial, &env);
set_irg_loopinfo_inconsistent(irg);
}
+ ir_free_resources(irg, IR_RESOURCE_IRN_LINK);
+
pmap_destroy(env.type2id_map);
del_set(env.opcode2id_map);
obstack_free(&env.obst, NULL);