#include "irgmod.h"
#include "debug.h"
+#include "tv_t.h"
+
/* we need the tarval_R and tarval_U */
#define tarval_R tarval_top
#define tarval_U tarval_bottom
static INLINE tarval *get_node_tarval(const ir_node *irn) {
lattice_elem_t type = get_node_type(irn);
- if (get_kind(type.tv) == k_tarval)
+ if (is_tarval(type.tv))
return type.tv;
return tarval_bottom;
} /* get_node_type */
static void default_compute(node_t *node) {
int i;
ir_node *irn = node->node;
- ir_mode *mode;
if (get_irn_pinned(irn) == op_pin_state_pinned) {
node_t *block = get_irn_node(get_nodes_block(irn));
return;
}
}
- mode = get_irn_mode(irn);
- if (! mode_is_data(mode))
- return;
/* if any of the data inputs have type top, the result is type top */
for (i = get_irn_arity(irn) - 1; i >= 0; --i) {
return;
}
}
+
node->type.tv = computed_value(irn);
} /* default_compute */
node->type = type;
} /* compute_Phi */
+/**
+ * (Re-)compute the type for a Sub. Special case: both nodes are congruent.
+ *
+ * @param node the node
+ */
+static void compute_Add(node_t *node) {
+ ir_node *sub = node->node;
+ node_t *l = get_irn_node(get_Add_left(sub));
+ node_t *r = get_irn_node(get_Add_right(sub));
+ lattice_elem_t a = l->type;
+ lattice_elem_t b = r->type;
+ node_t *block = get_irn_node(get_nodes_block(sub));
+ ir_mode *mode;
+
+ if (block->type.tv == tarval_U) {
+ node->type.tv = tarval_top;
+ return;
+ }
+
+ if (a.tv == tarval_top || b.tv == tarval_top) {
+ node->type.tv = tarval_top;
+ } else if (a.tv == tarval_bottom || b.tv == tarval_bottom) {
+ node->type.tv = tarval_bottom;
+ } else {
+ /* x + 0 = 0 + x = x, but beware of floating point +0 + -0, so we
+ must call tarval_add() first to handle this case! */
+ if (is_tarval(a.tv)) {
+ if (is_tarval(b.tv)) {
+ node->type.tv = tarval_add(a.tv, b.tv);
+ return;
+ }
+ mode = get_tarval_mode(a.tv);
+ if (a.tv == get_mode_null(mode)) {
+ node->type = b;
+ return;
+ }
+ } else if (is_tarval(b.tv)) {
+ mode = get_tarval_mode(b.tv);
+ if (b.tv == get_mode_null(mode)) {
+ node->type = a;
+ return;
+ }
+ }
+ node->type.tv = tarval_bottom;
+ }
+} /* compute_Add */
+
/**
* (Re-)compute the type for a Sub. Special case: both nodes are congruent.
*
} else if (a.tv == tarval_bottom || b.tv == tarval_bottom) {
node->type.tv = tarval_bottom;
} else {
- if (get_kind(a.tv) == k_tarval && get_kind(b.tv)== k_tarval)
+ if (is_tarval(a.tv) && is_tarval(b.tv))
node->type.tv = tarval_sub(a.tv, b.tv);
else
node->type.tv = tarval_bottom;
* (Re-)compute the type for a Proj(Cmp).
*
* @param node the node
+ * @param cond the predecessor Cmp node
*/
static void compute_Proj_Cmp(node_t *node, ir_node *cmp) {
ir_node *proj = node->node;
}
} /* compute_Proj_Cmp */
+/**
+ * (Re-)compute the type for a Proj(Cond).
+ *
+ * @param node the node
+ * @param cond the predecessor Cond node
+ */
+static void compute_Proj_Cond(node_t *node, ir_node *cond) {
+ ir_node *proj = node->node;
+ long pnc = get_Proj_proj(proj);
+ ir_node *sel = get_Cond_selector(cond);
+ node_t *selector = get_irn_node(sel);
+
+ if (get_irn_mode(sel) == mode_b) {
+ /* an IF */
+ if (pnc == pn_Cond_true) {
+ if (selector->type.tv == tarval_b_false) {
+ node->type.tv = tarval_U;
+ } else if (selector->type.tv == tarval_b_true) {
+ node->type.tv = tarval_R;
+ } else if (selector->type.tv == tarval_bottom) {
+ node->type.tv = tarval_R;
+ } else {
+ assert(selector->type.tv == tarval_top);
+ node->type.tv = tarval_U;
+ }
+ } else {
+ assert(pnc == pn_Cond_false);
+
+ if (selector->type.tv == tarval_b_false) {
+ node->type.tv = tarval_R;
+ } else if (selector->type.tv == tarval_b_true) {
+ node->type.tv = tarval_U;
+ } else if (selector->type.tv == tarval_bottom) {
+ node->type.tv = tarval_R;
+ } else {
+ assert(selector->type.tv == tarval_top);
+ node->type.tv = tarval_U;
+ }
+ }
+ } else {
+ /* an SWITCH */
+ if (selector->type.tv == tarval_bottom) {
+ node->type.tv = tarval_R;
+ } else if (selector->type.tv == tarval_top) {
+ node->type.tv = tarval_U;
+ } else {
+ long value = get_tarval_long(selector->type.tv);
+ if (pnc == get_Cond_defaultProj(cond)) {
+ /* default switch, have to check ALL other cases */
+ int i;
+
+ for (i = get_irn_n_outs(cond) - 1; i >= 0; --i) {
+ ir_node *succ = get_irn_out(cond, i);
+
+ if (succ == proj)
+ continue;
+ if (value == get_Proj_proj(succ)) {
+ /* we found a match, will NOT take the default case */
+ node->type.tv = tarval_U;
+ return;
+ }
+ }
+ /* all cases checked, no match, will take default case */
+ node->type.tv = tarval_R;
+ } else {
+ /* normal case */
+ node->type.tv = value == pnc ? tarval_R : tarval_U;
+ }
+ }
+ }
+} /* compute_Proj_Cond */
+
/**
* (Re-)compute the type for a Proj-Nodes.
*
/* the Proj_X from the Start is always reachable */
node->type.tv = tarval_R;
break;
+ case iro_Cond:
+ compute_Proj_Cond(node, pred);
+ break;
default:
default_compute(node);
}
SET(Block);
SET(Jmp);
SET(Phi);
+ SET(Add);
SET(Sub);
SET(SymConst);
+ SET(Proj);
SET(End);
} /* set_compute_functions */
void combo(ir_graph *irg) {
environment_t env;
- ir_node *start_bl, *initial_X;
+ ir_node *initial_X;
node_t *start;
ir_graph *rem = current_ir_graph;
FIRM_DBG_REGISTER(dbg, "firm.opt.combo");
firm_dbg_set_mask(dbg, SET_LEVEL_3);
+ DB((dbg, LEVEL_1, "Doing COMBO for %+F\n", irg));
+
obstack_init(&env.obst);
env.worklist = NULL;
env.cprop = NULL;
/* Place the START Node's partition on cprop.
Place the START Node on its local worklist. */
- start_bl = get_irg_start_block(irg);
- start = get_irn_node(start_bl);
- add_node_to_cprop(start, &env);
-
- /* set the initial exec to R */
initial_X = get_irg_initial_exec(irg);
- get_irn_node(initial_X)->type.tv = tarval_R;
+ start = get_irn_node(initial_X);
+ add_node_to_cprop(start, &env);
do {
propagate(&env);