+/**
+ * return the value of a Proj(Cmp)
+ *
+ * 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, see later.
+ */
+static tarval *computed_value_Proj_Cmp(ir_node *n)
+{
+ ir_node *a = get_Proj_pred(n);
+ ir_node *aa = get_Cmp_left(a);
+ ir_node *ab = get_Cmp_right(a);
+ long proj_nr = get_Proj_proj(n);
+
+ /*
+ * BEWARE: a == a is NOT always True for floating Point values, as
+ * NaN != NaN is defined, so we must check this here.
+ */
+ if (aa == ab && (
+ !mode_is_float(get_irn_mode(aa)) || proj_nr == pn_Cmp_Lt || proj_nr == pn_Cmp_Gt)
+ ) { /* 1.: */
+
+ /* 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 == pn_Cmp_Eq, mode_b) */
+ return new_tarval_from_long (proj_nr & pn_Cmp_Eq, mode_b);
+ }
+ else {
+ tarval *taa = value_of(aa);
+ tarval *tab = value_of(ab);
+ ir_mode *mode = get_irn_mode(aa);
+
+ /*
+ * The predecessors of Cmp are target values. We can evaluate
+ * the Cmp.
+ */
+ if ((taa != tarval_bad) && (tab != tarval_bad)) {
+ /* strange checks... */
+ pn_Cmp flags = tarval_cmp(taa, tab);
+ if (flags != pn_Cmp_False) {
+ return new_tarval_from_long (proj_nr & flags, mode_b);
+ }
+ }
+ /* for integer values, we can check against MIN/MAX */
+ else if (mode_is_int(mode)) {
+ /* MIN <=/> x. This results in true/false. */
+ if (taa == get_mode_min(mode)) {
+ /* a compare with the MIN value */
+ if (proj_nr == pn_Cmp_Le)
+ return get_tarval_b_true();
+ else if (proj_nr == pn_Cmp_Gt)
+ return get_tarval_b_false();
+ }
+ /* x >=/< MIN. This results in true/false. */
+ else
+ if (tab == get_mode_min(mode)) {
+ /* a compare with the MIN value */
+ if (proj_nr == pn_Cmp_Ge)
+ return get_tarval_b_true();
+ else if (proj_nr == pn_Cmp_Lt)
+ return get_tarval_b_false();
+ }
+ /* MAX >=/< x. This results in true/false. */
+ else if (taa == get_mode_max(mode)) {
+ if (proj_nr == pn_Cmp_Ge)
+ return get_tarval_b_true();
+ else if (proj_nr == pn_Cmp_Lt)
+ return get_tarval_b_false();
+ }
+ /* x <=/> MAX. This results in true/false. */
+ else if (tab == get_mode_max(mode)) {
+ if (proj_nr == pn_Cmp_Le)
+ return get_tarval_b_true();
+ else if (proj_nr == pn_Cmp_Gt)
+ return get_tarval_b_false();
+ }
+ }
+ /*
+ * The predecessors are Allocs or (void*)(0) constants. Allocs never
+ * return NULL, they raise an exception. Therefore we can predict
+ * the Cmp result.
+ */
+ else {
+ 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 NULL */
+ (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 NULL 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 & pn_Cmp_Ne, mode_b);
+ }
+ }
+
+ return computed_value_Cmp_Confirm(a, aa, ab, proj_nr);
+}
+