+ if (block->type.tv == tarval_unreachable) {
+ node->type.tv = tarval_top;
+ 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) {
+ ir_node *pred = get_irn_n(irn, i);
+ node_t *p = get_irn_node(pred);
+
+ if (p->type.tv == tarval_top) {
+ node->type.tv = tarval_top;
+ return;
+ }
+ }
+
+ if (get_irn_mode(node->node) == mode_X)
+ node->type.tv = tarval_reachable;
+ else
+ node->type.tv = computed_value(irn);
+} /* default_compute */
+
+/**
+ * (Re-)compute the type for a Block node.
+ *
+ * @param node the node
+ */
+static void compute_Block(node_t *node) {
+ int i;
+ ir_node *block = node->node;
+
+ if (block == get_irg_start_block(current_ir_graph)) {
+ /* start block is always reachable */
+ node->type.tv = tarval_reachable;
+ return;
+ }
+
+ for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i) {
+ node_t *pred = get_irn_node(get_Block_cfgpred(block, i));
+
+ if (pred->type.tv == tarval_reachable) {
+ /* A block is reachable, if at least of predecessor is reachable. */
+ node->type.tv = tarval_reachable;
+ return;
+ }
+ }
+ node->type.tv = tarval_top;
+} /* compute_Block */
+
+/**
+ * (Re-)compute the type for a Bad node.
+ *
+ * @param node the node
+ */
+static void compute_Bad(node_t *node) {
+ /* Bad nodes ALWAYS compute Top */
+ node->type.tv = tarval_top;
+} /* compute_Bad */
+
+/**
+ * (Re-)compute the type for an Unknown node.
+ *
+ * @param node the node
+ */
+static void compute_Unknown(node_t *node) {
+ /* While Unknown nodes should compute Top this is dangerous:
+ * a Top input to a Cond would lead to BOTH control flows unreachable.
+ * While this is correct in the given semantics, it would destroy the Firm
+ * graph.
+ *
+ * It would be safe to compute Top IF it can be assured, that only Cmp
+ * nodes are inputs to Conds. We check that first.
+ * This is the way Frontends typically build Firm, but some optimizations
+ * (cond_eval for instance) might replace them by Phib's...
+ */
+ node->type.tv = tarval_UNKNOWN;
+} /* compute_Unknown */
+
+/**
+ * (Re-)compute the type for a Jmp node.
+ *
+ * @param node the node
+ */
+static void compute_Jmp(node_t *node) {
+ node_t *block = get_irn_node(get_nodes_block(node->node));
+
+ node->type = block->type;
+} /* compute_Jmp */
+
+/**
+ * (Re-)compute the type for the Return node.
+ *
+ * @param node the node
+ */
+static void compute_Return(node_t *node) {
+ /* The Return node is NOT dead if it is in a reachable block.
+ * This is already checked in compute(). so we can return
+ * Reachable here. */
+ node->type.tv = tarval_reachable;
+} /* compute_Return */
+
+/**
+ * (Re-)compute the type for the End node.
+ *
+ * @param node the node
+ */
+static void compute_End(node_t *node) {
+ /* the End node is NOT dead of course */
+ node->type.tv = tarval_reachable;
+} /* compute_End */
+
+/**
+ * (Re-)compute the type for a SymConst node.
+ *
+ * @param node the node
+ */
+static void compute_SymConst(node_t *node) {
+ ir_node *irn = node->node;
+ node_t *block = get_irn_node(get_nodes_block(irn));
+
+ if (block->type.tv == tarval_unreachable) {
+ node->type.tv = tarval_top;
+ return;
+ }
+ switch (get_SymConst_kind(irn)) {
+ case symconst_addr_ent:
+ /* case symconst_addr_name: cannot handle this yet */
+ node->type.sym = get_SymConst_symbol(irn);
+ break;
+ default:
+ node->type.tv = computed_value(irn);
+ }
+} /* compute_SymConst */
+
+/**
+ * (Re-)compute the type for a Phi node.
+ *
+ * @param node the node
+ */
+static void compute_Phi(node_t *node) {
+ int i;
+ ir_node *phi = node->node;
+ lattice_elem_t type;
+
+ /* if a Phi is in a unreachable block, its type is TOP */
+ node_t *block = get_irn_node(get_nodes_block(phi));
+
+ if (block->type.tv == tarval_unreachable) {
+ node->type.tv = tarval_top;
+ return;
+ }
+
+ /* Phi implements the Meet operation */
+ type.tv = tarval_top;
+ for (i = get_Phi_n_preds(phi) - 1; i >= 0; --i) {
+ node_t *pred = get_irn_node(get_Phi_pred(phi, i));
+ node_t *pred_X = get_irn_node(get_Block_cfgpred(block->node, i));
+
+ if (pred_X->type.tv == tarval_unreachable || pred->type.tv == tarval_top) {
+ /* ignore TOP inputs: We must check here for unreachable blocks,
+ because Firm constants live in the Start Block are NEVER Top.
+ Else, a Phi (1,2) will produce Bottom, even if the 2 for instance
+ comes from a unreachable input. */
+ continue;
+ }
+ if (pred->type.tv == tarval_bottom) {
+ node->type.tv = tarval_bottom;
+ return;
+ } else if (type.tv == tarval_top) {
+ /* first constant found */
+ type = pred->type;
+ } else if (type.tv != pred->type.tv) {
+ /* different constants or tarval_bottom */
+ node->type.tv = tarval_bottom;
+ return;
+ }
+ /* else nothing, constants are the same */
+ }
+ node->type = type;
+} /* compute_Phi */
+
+/**
+ * (Re-)compute the type for an Add. Special case: one nodes is a Zero Const.
+ *
+ * @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;
+ ir_mode *mode;
+
+ 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.
+ *
+ * @param node the node
+ */
+static void compute_Sub(node_t *node) {
+ ir_node *sub = node->node;
+ node_t *l = get_irn_node(get_Sub_left(sub));
+ node_t *r = get_irn_node(get_Sub_right(sub));
+ lattice_elem_t a = l->type;
+ lattice_elem_t b = r->type;
+ tarval *tv;
+
+ if (a.tv == tarval_top || b.tv == tarval_top) {
+ node->type.tv = tarval_top;
+ } else if (is_con(a) && is_con(b)) {
+ if (is_tarval(a.tv) && is_tarval(b.tv)) {
+ node->type.tv = tarval_sub(a.tv, b.tv, get_irn_mode(sub));
+ } else if (is_tarval(a.tv) && tarval_is_null(a.tv)) {
+ node->type = b;
+ } else if (is_tarval(b.tv) && tarval_is_null(b.tv)) {
+ node->type = a;
+ } else {
+ node->type.tv = tarval_bottom;
+ }
+ node->by_all_const = 1;
+ } else if (r->part == l->part &&
+ (!mode_is_float(get_irn_mode(l->node)))) {
+ /*
+ * BEWARE: a - a is NOT always 0 for floating Point values, as
+ * NaN op NaN = NaN, so we must check this here.
+ */
+ ir_mode *mode = get_irn_mode(sub);
+ tv = get_mode_null(mode);
+
+ /* if the node was ONCE evaluated by all constants, but now
+ this breaks AND we get from the argument partitions a different
+ result, switch to bottom.
+ This happens because initially all nodes are in the same partition ... */
+ if (node->by_all_const && node->type.tv != tv)
+ tv = tarval_bottom;
+ node->type.tv = tv;
+ } else {
+ node->type.tv = tarval_bottom;
+ }
+} /* compute_Sub */
+
+/**
+ * (Re-)compute the type for an Eor. Special case: both nodes are congruent.
+ *
+ * @param node the node
+ */
+static void compute_Eor(node_t *node) {
+ ir_node *eor = node->node;
+ node_t *l = get_irn_node(get_Eor_left(eor));
+ node_t *r = get_irn_node(get_Eor_right(eor));
+ lattice_elem_t a = l->type;
+ lattice_elem_t b = r->type;
+ tarval *tv;
+
+ if (a.tv == tarval_top || b.tv == tarval_top) {
+ node->type.tv = tarval_top;
+ } else if (is_con(a) && is_con(b)) {
+ if (is_tarval(a.tv) && is_tarval(b.tv)) {
+ node->type.tv = tarval_eor(a.tv, b.tv);
+ } else if (is_tarval(a.tv) && tarval_is_null(a.tv)) {
+ node->type = b;
+ } else if (is_tarval(b.tv) && tarval_is_null(b.tv)) {
+ node->type = a;
+ } else {
+ node->type.tv = tarval_bottom;
+ }
+ node->by_all_const = 1;
+ } else if (r->part == l->part) {
+ ir_mode *mode = get_irn_mode(eor);
+ tv = get_mode_null(mode);
+
+ /* if the node was ONCE evaluated by all constants, but now
+ this breaks AND we get from the argument partitions a different
+ result, switch to bottom.
+ This happens because initially all nodes are in the same partition ... */
+ if (node->by_all_const && node->type.tv != tv)
+ tv = tarval_bottom;
+ node->type.tv = tv;
+ } else {
+ node->type.tv = tarval_bottom;
+ }
+} /* compute_Eor */
+
+/**
+ * (Re-)compute the type for Cmp.
+ *
+ * @param node the node
+ */
+static void compute_Cmp(node_t *node) {
+ ir_node *cmp = node->node;
+ node_t *l = get_irn_node(get_Cmp_left(cmp));
+ node_t *r = get_irn_node(get_Cmp_right(cmp));
+ lattice_elem_t a = l->type;
+ lattice_elem_t b = r->type;
+
+ if (a.tv == tarval_top || b.tv == tarval_top) {
+ node->type.tv = tarval_top;
+ } else if (r->part == l->part) {
+ /* both nodes congruent, we can probably do something */
+ node->type.tv = tarval_b_true;
+ } else if (is_con(a) && is_con(b)) {
+ /* both nodes are constants, we can probably do something */
+ node->type.tv = tarval_b_true;
+ } else {
+ node->type.tv = tarval_bottom;
+ }
+} /* compute_Cmp */
+
+/**
+ * (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;
+ node_t *l = get_irn_node(get_Cmp_left(cmp));
+ node_t *r = get_irn_node(get_Cmp_right(cmp));
+ lattice_elem_t a = l->type;
+ lattice_elem_t b = r->type;
+ pn_Cmp pnc = get_Proj_proj(proj);
+ tarval *tv;
+
+ if (a.tv == tarval_top || b.tv == tarval_top) {
+ node->type.tv = tarval_undefined;
+ } else if (is_con(a) && is_con(b)) {
+ default_compute(node);
+ node->by_all_const = 1;
+ } else if (r->part == l->part &&
+ (!mode_is_float(get_irn_mode(l->node)) || pnc == pn_Cmp_Lt || pnc == pn_Cmp_Gt)) {
+ /*
+ * BEWARE: a == a is NOT always True for floating Point values, as
+ * NaN != NaN is defined, so we must check this here.
+ */
+ tv = pnc & pn_Cmp_Eq ? tarval_b_true: tarval_b_false;
+
+ /* if the node was ONCE evaluated by all constants, but now
+ this breaks AND we get from the argument partitions a different
+ result, switch to bottom.
+ This happens because initially all nodes are in the same partition ... */
+ if (node->by_all_const && node->type.tv != tv)
+ tv = tarval_bottom;
+ node->type.tv = tv;
+ } else {
+ node->type.tv = tarval_bottom;
+ }
+} /* 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_unreachable;
+ } else if (selector->type.tv == tarval_b_true) {
+ node->type.tv = tarval_reachable;
+ } else if (selector->type.tv == tarval_bottom) {
+ node->type.tv = tarval_reachable;
+ } else {
+ assert(selector->type.tv == tarval_top);
+ /* any condition based on Top is "!=" */
+ node->type.tv = tarval_unreachable;
+ }
+ } else {
+ assert(pnc == pn_Cond_false);
+
+ if (selector->type.tv == tarval_b_false) {
+ node->type.tv = tarval_reachable;
+ } else if (selector->type.tv == tarval_b_true) {
+ node->type.tv = tarval_unreachable;
+ } else if (selector->type.tv == tarval_bottom) {
+ node->type.tv = tarval_reachable;
+ } else {
+ assert(selector->type.tv == tarval_top);
+ /* any condition based on Top is "!=" */
+ node->type.tv = tarval_reachable;
+ }
+ }
+ } else {
+ /* an SWITCH */
+ if (selector->type.tv == tarval_bottom) {
+ node->type.tv = tarval_reachable;
+ } else if (selector->type.tv == tarval_top) {
+ if (pnc == get_Cond_defaultProj(cond)) {
+ /* a switch based of Top is always "default" */
+ node->type.tv = tarval_reachable;
+ } else
+ node->type.tv = tarval_unreachable;
+ } 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_unreachable;
+ return;
+ }