+ return get_Const_tarval(n);
+}
+
+/**
+ * return the value of a 'sizeof' SymConst
+ */
+static tarval *computed_value_SymConst(ir_node *n)
+{
+ if ((get_SymConst_kind(n) == symconst_size) &&
+ (get_type_state(get_SymConst_type(n))) == layout_fixed)
+ return new_tarval_from_long(get_type_size_bytes(get_SymConst_type(n)), get_irn_mode(n));
+ return tarval_bad;
+}
+
+/**
+ * return the value of an Add
+ */
+static tarval *computed_value_Add(ir_node *n)
+{
+ ir_node *a = get_Add_left(n);
+ ir_node *b = get_Add_right(n);
+
+ tarval *ta = value_of(a);
+ tarval *tb = value_of(b);
+
+ if ((ta != tarval_bad) && (tb != tarval_bad) && (get_irn_mode(a) == get_irn_mode(b)))
+ return tarval_add(ta, tb);
+
+ return tarval_bad;
+}
+
+/**
+ * return the value of a Sub
+ * Special case: a - a
+ */
+static tarval *computed_value_Sub(ir_node *n)
+{
+ ir_node *a = get_Sub_left(n);
+ ir_node *b = get_Sub_right(n);
+ tarval *ta;
+ tarval *tb;
+
+ /* a - a */
+ if (a == b && !is_Bad(a))
+ return get_tarval_null(get_irn_mode(n));
+
+ ta = value_of(a);
+ tb = value_of(b);
+
+ if ((ta != tarval_bad) && (tb != tarval_bad) && (get_irn_mode(a) == get_irn_mode(b)))
+ return tarval_sub(ta, tb);
+
+ return tarval_bad;
+}
+
+/**
+ * return the value of an unary Minus
+ */
+static tarval *computed_value_Minus(ir_node *n)
+{
+ ir_node *a = get_Minus_op(n);
+ tarval *ta = value_of(a);
+
+ if ((ta != tarval_bad) && mode_is_signed(get_irn_mode(a)))
+ return tarval_neg(ta);
+
+ return tarval_bad;
+}
+
+/**
+ * return the value of a Mul
+ */
+static tarval *computed_value_Mul(ir_node *n)
+{
+ ir_node *a = get_Mul_left(n);
+ ir_node *b = get_Mul_right(n);
+
+ tarval *ta = value_of(a);
+ tarval *tb = value_of(b);
+
+ if ((ta != tarval_bad) && (tb != tarval_bad) && (get_irn_mode(a) == get_irn_mode(b))) {
+ return tarval_mul(ta, tb);
+ } else {
+ /* a*0 = 0 or 0*b = 0:
+ calls computed_value recursive and returns the 0 with proper
+ mode. */
+ if ((ta != tarval_bad) && (ta == get_mode_null(get_tarval_mode(ta))))
+ return ta;
+ if ((tb != tarval_bad) && (tb == get_mode_null(get_tarval_mode(tb))))
+ return tb;
+ }
+ return tarval_bad;
+}
+
+/**
+ * return the value of a floating point Quot
+ */
+static tarval *computed_value_Quot(ir_node *n)
+{
+ ir_node *a = get_Quot_left(n);
+ ir_node *b = get_Quot_right(n);
+
+ tarval *ta = value_of(a);
+ tarval *tb = value_of(b);
+
+ /* This was missing in original implementation. Why? */
+ if ((ta != tarval_bad) && (tb != tarval_bad) && (get_irn_mode(a) == get_irn_mode(b))) {
+ if (tb != get_mode_null(get_tarval_mode(tb))) /* div by zero: return tarval_bad */
+ return tarval_quo(ta, tb);
+ }
+ return tarval_bad;
+}
+
+/**
+ * calculate the value of an integer Div of two nodes
+ * Special case: 0 / b
+ */
+static tarval *do_computed_value_Div(ir_node *a, ir_node *b)
+{
+ tarval *ta = value_of(a);
+ tarval *tb = value_of(b);
+
+ /* Compute c1 / c2 or 0 / a, a != 0 */
+ if (ta != tarval_bad) {
+ if ((tb != tarval_bad) && (tb != get_mode_null(get_irn_mode(b)))) /* div by zero: return tarval_bad */
+ return tarval_div(ta, tb);
+ else if (ta == get_mode_null(get_tarval_mode(ta))) /* 0 / b == 0 */
+ return ta;
+ }
+ return tarval_bad;
+}
+
+/**
+ * return the value of an integer Div
+ */
+static tarval *computed_value_Div(ir_node *n)
+{
+ return do_computed_value_Div(get_Div_left(n), get_Div_right(n));
+}
+
+/**
+ * calculate the value of an integer Mod of two nodes
+ * Special case: a % 1
+ */
+static tarval *do_computed_value_Mod(ir_node *a, ir_node *b)
+{
+ tarval *ta = value_of(a);
+ tarval *tb = value_of(b);
+
+ /* Compute c1 % c2 or a % 1 */
+ if (tb != tarval_bad) {
+ if ((ta != tarval_bad) && (tb != get_mode_null(get_tarval_mode(tb)))) /* div by zero: return tarval_bad */
+ return tarval_mod(ta, tb);
+ else if (tb == get_mode_one(get_tarval_mode(tb))) /* x mod 1 == 0 */
+ return get_mode_null(get_irn_mode(a));
+ }
+
+ return tarval_bad;
+}
+
+/**
+ * return the value of an integer Mod
+ */
+static tarval *computed_value_Mod(ir_node *n)
+{
+ return do_computed_value_Mod(get_Mod_left(n), get_Mod_right(n));
+}
+
+/**
+ * return the value of an Abs
+ */
+static tarval *computed_value_Abs(ir_node *n)
+{
+ ir_node *a = get_Abs_op(n);
+ tarval *ta = value_of(a);
+
+ if (ta != tarval_bad)
+ return tarval_abs(ta);
+
+ return tarval_bad;
+}
+
+/**
+ * return the value of an And
+ * Special case: a & 0, 0 & b
+ */
+static tarval *computed_value_And(ir_node *n)
+{
+ ir_node *a = get_And_left(n);
+ ir_node *b = get_And_right(n);
+
+ tarval *ta = value_of(a);
+ tarval *tb = value_of(b);
+
+ if ((ta != tarval_bad) && (tb != tarval_bad)) {
+ return tarval_and (ta, tb);
+ } else {
+ tarval *v;
+
+ if ( (classify_tarval ((v = ta)) == TV_CLASSIFY_NULL)
+ || (classify_tarval ((v = tb)) == TV_CLASSIFY_NULL)) {
+ return v;
+ }
+ }
+ return tarval_bad;
+}
+
+/**
+ * return the value of an Or
+ * Special case: a | 1...1, 1...1 | b
+ */
+static tarval *computed_value_Or(ir_node *n)
+{
+ ir_node *a = get_Or_left(n);
+ ir_node *b = get_Or_right(n);
+
+ tarval *ta = value_of(a);
+ tarval *tb = value_of(b);
+
+ if ((ta != tarval_bad) && (tb != tarval_bad)) {
+ return tarval_or (ta, tb);
+ } else {
+ tarval *v;
+ if ( (classify_tarval ((v = ta)) == TV_CLASSIFY_ALL_ONE)
+ || (classify_tarval ((v = tb)) == TV_CLASSIFY_ALL_ONE)) {
+ return v;
+ }
+ }
+ return tarval_bad;
+}
+
+/**
+ * return the value of an Eor
+ */
+static tarval *computed_value_Eor(ir_node *n)
+{
+ ir_node *a = get_Eor_left(n);
+ ir_node *b = get_Eor_right(n);
+
+ tarval *ta, *tb;
+
+ if (a == b)
+ return get_tarval_null(get_irn_mode(n));
+
+ ta = value_of(a);
+ tb = value_of(b);
+
+ if ((ta != tarval_bad) && (tb != tarval_bad)) {
+ return tarval_eor (ta, tb);
+ }
+ return tarval_bad;
+}
+
+/**
+ * return the value of a Not
+ */
+static tarval *computed_value_Not(ir_node *n)
+{
+ ir_node *a = get_Not_op(n);
+ tarval *ta = value_of(a);
+
+ if (ta != tarval_bad)
+ return tarval_not(ta);
+
+ return tarval_bad;
+}
+
+/**
+ * return the value of a Shl
+ */
+static tarval *computed_value_Shl(ir_node *n)
+{
+ ir_node *a = get_Shl_left(n);
+ ir_node *b = get_Shl_right(n);
+
+ tarval *ta = value_of(a);
+ tarval *tb = value_of(b);
+
+ if ((ta != tarval_bad) && (tb != tarval_bad)) {
+ return tarval_shl (ta, tb);
+ }
+ return tarval_bad;
+}
+
+/**
+ * return the value of a Shr
+ */
+static tarval *computed_value_Shr(ir_node *n)
+{
+ ir_node *a = get_Shr_left(n);
+ ir_node *b = get_Shr_right(n);
+
+ tarval *ta = value_of(a);
+ tarval *tb = value_of(b);
+
+ if ((ta != tarval_bad) && (tb != tarval_bad)) {
+ return tarval_shr (ta, tb);
+ }
+ return tarval_bad;
+}
+
+/**
+ * return the value of a Shrs
+ */
+static tarval *computed_value_Shrs(ir_node *n)
+{
+ ir_node *a = get_Shrs_left(n);
+ ir_node *b = get_Shrs_right(n);
+
+ tarval *ta = value_of(a);
+ tarval *tb = value_of(b);
+
+ if ((ta != tarval_bad) && (tb != tarval_bad)) {
+ return tarval_shrs (ta, tb);
+ }
+ return tarval_bad;
+}
+
+/**
+ * return the value of a Rot
+ */
+static tarval *computed_value_Rot(ir_node *n)
+{
+ ir_node *a = get_Rot_left(n);
+ ir_node *b = get_Rot_right(n);
+
+ tarval *ta = value_of(a);
+ tarval *tb = value_of(b);
+
+ if ((ta != tarval_bad) && (tb != tarval_bad)) {
+ return tarval_rot (ta, tb);
+ }
+ return tarval_bad;
+}
+
+/**
+ * return the value of a Conv
+ */
+static tarval *computed_value_Conv(ir_node *n)
+{
+ ir_node *a = get_Conv_op(n);
+ tarval *ta = value_of(a);
+
+ if (ta != tarval_bad)
+ return tarval_convert_to(ta, get_irn_mode(n));
+
+ return tarval_bad;
+}
+
+/**
+ * return the value of a Proj, handle Proj(Cmp), Proj(Div), Proj(Mod), Proj(DivMod)
+ */
+static tarval *computed_value_Proj(ir_node *n)
+{
+ ir_node *a = get_Proj_pred(n);
+ ir_node *aa, *ab;
+ long proj_nr;
+
+ /* Optimize Cmp nodes.
+ This performs a first step of unreachable code elimination.
+ Proj can not be computed, but folding a Cmp above the Proj here is
+ not as wasteful as folding a Cmp into a Tuple of 16 Consts of which
+ only 1 is used.
+ There are several case where we can evaluate a Cmp node:
+ 1. The nodes compared are both the same. If we compare for
+ equal, greater equal, ... this will return true, else it
+ will return false. This step relies on cse.
+ 2. The predecessors of Cmp are target values. We can evaluate
+ the Cmp.
+ 3. The predecessors are Allocs or void* constants. Allocs never
+ return NULL, they raise an exception. Therefore we can predict
+ the Cmp result. */
+ switch (get_irn_opcode(a)) {
+ case iro_Cmp:
+ aa = get_Cmp_left(a);
+ ab = get_Cmp_right(a);
+ proj_nr = get_Proj_proj(n);
+
+ if (aa == ab && !mode_is_float(get_irn_mode(aa))) { /* 1.: */
+ /* BEWARE: a == a is NOT always True for floating Point!!! */
+ /* This is a trick with the bits used for encoding the Cmp
+ Proj numbers, the following statement is not the same:
+ return new_tarval_from_long (proj_nr == Eq, mode_b) */
+ return new_tarval_from_long (proj_nr & Eq, mode_b);
+ } else {
+ tarval *taa = value_of(aa);
+ tarval *tab = value_of(ab);
+
+ if ((taa != tarval_bad) && (tab != tarval_bad)) { /* 2.: */
+ /* strange checks... */
+ pnc_number flags = tarval_cmp (taa, tab);
+ if (flags != False) {
+ return new_tarval_from_long (proj_nr & flags, mode_b);
+ }
+ } else { /* check for 3.: */
+ ir_node *aaa = skip_Id(skip_Proj(aa));
+ ir_node *aba = skip_Id(skip_Proj(ab));
+
+ if ( ( (/* aa is ProjP and aaa is Alloc */
+ (get_irn_op(aa) == op_Proj)
+ && (mode_is_reference(get_irn_mode(aa)))
+ && (get_irn_op(aaa) == op_Alloc))
+ && ( (/* ab is constant void */
+ (get_irn_op(ab) == op_Const)
+ && (mode_is_reference(get_irn_mode(ab)))
+ && (get_Const_tarval(ab) == get_mode_null(get_irn_mode(ab))))
+ || (/* ab is other Alloc */
+ (get_irn_op(ab) == op_Proj)
+ && (mode_is_reference(get_irn_mode(ab)))
+ && (get_irn_op(aba) == op_Alloc)
+ && (aaa != aba))))
+ || (/* aa is void and aba is Alloc */
+ (get_irn_op(aa) == op_Const)
+ && (mode_is_reference(get_irn_mode(aa)))
+ && (get_Const_tarval(aa) == get_mode_null(get_irn_mode(aa)))
+ && (get_irn_op(ab) == op_Proj)
+ && (mode_is_reference(get_irn_mode(ab)))
+ && (get_irn_op(aba) == op_Alloc)))
+ /* 3.: */
+ return new_tarval_from_long (proj_nr & Ne, mode_b);
+ }
+ }
+ break;
+
+ case iro_DivMod:
+ /* compute either the Div or the Mod part */
+ proj_nr = get_Proj_proj(n);
+ if (proj_nr == pn_DivMod_res_div)
+ return do_computed_value_Div(get_DivMod_left(a), get_DivMod_right(a));
+ else if (proj_nr == pn_DivMod_res_mod)
+ return do_computed_value_Mod(get_DivMod_left(a), get_DivMod_right(a));
+ break;
+
+ case iro_Div:
+ if (get_Proj_proj(n) == pn_Div_res)
+ return computed_value(a);
+ break;
+
+ case iro_Mod:
+ if (get_Proj_proj(n) == pn_Mod_res)
+ return computed_value(a);
+ break;
+
+ default: