/** * analyze enough to decide if we should lower the switch */ static void analyse_switch0(switch_info_t *info, ir_node *switchn) { const ir_switch_table *table = get_Switch_table(switchn); size_t n_entries = ir_switch_table_get_n_entries(table); ir_mode *mode = get_irn_mode(get_Switch_selector(switchn)); ir_tarval *switch_min = get_mode_max(mode); ir_tarval *switch_max = get_mode_min(mode); unsigned num_cases = 0; for (size_t e = 0; e < n_entries; ++e) { const ir_switch_table_entry *entry = ir_switch_table_get_entry_const(table, e); if (entry->pn == pn_Switch_default) continue; if (tarval_cmp(entry->min, switch_min) == ir_relation_less) switch_min = entry->min; if (tarval_cmp(entry->max, switch_max) == ir_relation_greater) switch_max = entry->max; ++num_cases; } info->switchn = switchn; info->switch_min = switch_min; info->switch_max = switch_max; info->num_cases = num_cases; }
bool enum_bitfield_big_enough(enum_t *enume, type_t *base_type, unsigned bitfield_size) { ir_mode *mode = get_ir_mode_storage(base_type); ir_tarval *max = get_mode_max(mode); ir_tarval *min = get_mode_min(mode); bool is_signed = is_type_signed(base_type); unsigned mode_size = get_mode_size_bits(mode); unsigned shift_amount = mode_size - bitfield_size + is_signed; ir_tarval *adjusted_max; ir_tarval *adjusted_min; /* corner case: signed mode with just sign bit results in shift_amount * being as big as mode_size triggering "modulo shift" which is not what * we want here. */ if (shift_amount >= mode_size) { assert(bitfield_size == 1 && mode_is_signed(mode)); adjusted_max = get_mode_null(mode); adjusted_min = get_mode_all_one(mode); } else { adjusted_max = tarval_shr_unsigned(max, shift_amount); adjusted_min = tarval_shrs_unsigned(min, shift_amount); } for (entity_t *entry = enume->first_value; entry != NULL && entry->kind == ENTITY_ENUM_VALUE; entry = entry->base.next) { ir_tarval *tv = get_enum_value(&entry->enum_value); if (tv == NULL) continue; ir_tarval *tvc = tarval_convert_to(tv, mode); if (tarval_cmp(tvc, adjusted_min) == ir_relation_less || tarval_cmp(tvc, adjusted_max) == ir_relation_greater) { return false; } } return true; }
static ir_tarval *fold_binary_comparison( binary_expression_t const *const binexpr) { ir_tarval *const left = fold_expression(binexpr->left); ir_tarval *const right = fold_expression(binexpr->right); type_t *const atype = skip_typeref(binexpr->left->base.type); ir_mode *const amode = get_ir_mode_arithmetic(atype); assert(amode == get_ir_mode_arithmetic(skip_typeref(binexpr->right->base.type))); ir_tarval *const lefta = tarval_convert_to(left, amode); ir_tarval *const righta = tarval_convert_to(right, amode); type_t *const type = skip_typeref(binexpr->base.type); ir_mode *const mode = get_ir_mode_arithmetic(type); ir_relation const rel = get_relation(binexpr->base.kind); return create_tarval_from_bool(mode, tarval_cmp(lefta, righta) & rel); }
/* * Check, if the value of a node is != 0. * * This is a often needed case, so we handle here Confirm * nodes too. */ int value_not_zero(const ir_node *n, const ir_node **confirm) { #define RET_ON(x) if (x) { *confirm = n; return 1; } break ir_tarval *tv; ir_mode *mode = get_irn_mode(n); ir_relation relation; *confirm = NULL; /* there might be several Confirms one after other that form an interval */ for (;;) { if (is_Minus(n)) { /* we can safely skip Minus when checking for != 0 */ n = get_Minus_op(n); continue; } if (! is_Confirm(n)) break; /* * Note: A Confirm is never after a Const. So, * we simply can check the bound for being a Const * without the fear that is might be hidden by a further Confirm. */ tv = value_of(get_Confirm_bound(n)); if (tv == tarval_bad) { n = get_Confirm_value(n); continue; } relation = tarval_cmp(tv, get_mode_null(mode)); /* * Beware: C might by a NaN. It is not clear, what we should do * than. Of course a NaN is != 0, but we might use this function * to remove up Exceptions, and NaN's might generate Exception. * So, we do NOT handle NaNs here for safety. * * Note that only the C != 0 case need additional checking. */ switch (get_Confirm_relation(n)) { case ir_relation_equal: /* n == C /\ C != 0 ==> n != 0 */ RET_ON(relation != ir_relation_equal && relation != ir_relation_unordered); case ir_relation_less_greater: /* n != C /\ C == 0 ==> n != 0 */ RET_ON(relation == ir_relation_equal); case ir_relation_less: /* n < C /\ C <= 0 ==> n != 0 */ RET_ON(relation == ir_relation_less || relation == ir_relation_equal); case ir_relation_less_equal: /* n <= C /\ C < 0 ==> n != 0 */ RET_ON(relation == ir_relation_less); case ir_relation_greater_equal: /* n >= C /\ C > 0 ==> n != 0 */ RET_ON(relation == ir_relation_greater); case ir_relation_greater: /* n > C /\ C >= 0 ==> n != 0 */ RET_ON(relation == ir_relation_greater || relation == ir_relation_equal); default: break; } n = get_Confirm_value(n); } /* global entities are never NULL */ if (is_SymConst_addr_ent(n)) return true; tv = value_of(n); if (tv == tarval_bad) return false; relation = tarval_cmp(tv, get_mode_null(mode)); /* again, need check for NaN */ return (relation != ir_relation_equal) && (relation != ir_relation_unordered); #undef RET_ON }
/** * Try to evaluate l_iv relation r_iv. * * @param l_iv the left interval * @param r_iv the right interval * @param relation the compare relation * * @return * tarval_b_true or tarval_b_false it it can be evaluated, * tarval_bad else */ static ir_tarval *(compare_iv)(const interval_t *l_iv, const interval_t *r_iv, ir_relation relation) { ir_relation res; unsigned flags; ir_tarval *tv_true = tarval_b_true, *tv_false = tarval_b_false; /* if one interval contains NaNs, we cannot evaluate anything */ if (! l_iv || ! r_iv) return tarval_bad; /* we can only check ordered relations */ if (relation & ir_relation_unordered) { ir_tarval *t; relation = get_negated_relation(relation); t = tv_true; tv_true = tv_false; tv_false = t; } /* if we have > or >=, we do the inverse to save some cases */ if (relation == ir_relation_greater_equal || relation == ir_relation_greater) { const interval_t *t; relation = get_inversed_relation(relation); t = l_iv; l_iv = r_iv; r_iv = t; } /* now, only the following cases remains */ switch (relation) { case ir_relation_equal: /* two intervals can be compared for equality only if they are a single value */ if (l_iv->min == l_iv->max && r_iv->min == r_iv->max) return tarval_cmp(l_iv->min, r_iv->min) == ir_relation_equal ? tv_true : tv_false; /* if both intervals do not intersect, it is never equal */ res = tarval_cmp(l_iv->max, r_iv->min); /* b < c ==> [a,b] != [c,d] */ if (res == ir_relation_less) return tv_false; /* b <= c ==> [a,b) != [c,d] AND [a,b] != (c,d] */ if ((l_iv->flags & MAX_EXCLUDED || r_iv->flags & MIN_EXCLUDED) && (res == ir_relation_equal)) return tv_false; res = tarval_cmp(r_iv->max, l_iv->min); /* d < a ==> [c,d] != [a,b] */ if (res == ir_relation_less) return tv_false; /* d <= a ==> [c,d) != [a,b] AND [c,d] != (a,b] */ if ((r_iv->flags & MAX_EXCLUDED || l_iv->flags & MIN_EXCLUDED) && (res == ir_relation_equal)) return tv_false; break; case ir_relation_less_greater: /* two intervals can be compared for not equality only if they are a single value */ if (l_iv->min == l_iv->max && r_iv->min == r_iv->max) return tarval_cmp(l_iv->min, r_iv->min) != ir_relation_equal ? tv_true : tv_false; break; case ir_relation_less: res = tarval_cmp(l_iv->max, r_iv->min); /* [a, b] < [c, d] <==> b < c */ if (res == ir_relation_less) return tv_true; /* if one border is excluded, b <= c is enough */ if ((l_iv->flags & MAX_EXCLUDED || r_iv->flags & MIN_EXCLUDED) && res == ir_relation_equal) return tv_true; /* [a, b] >= [c, d] <==> a > d */ res = tarval_cmp(l_iv->min, r_iv->max); if (res == ir_relation_greater) return tv_false; /* if one border is excluded, a >= d is enough */ if ((l_iv->flags & MIN_EXCLUDED || r_iv->flags & MAX_EXCLUDED) && res == ir_relation_equal) return tv_false; break; case ir_relation_less_equal: /* [a, b) <= [c, d] or [a, b] <= (c, d] <==> b <= c */ flags = (l_iv->flags & MAX_EXCLUDED) | (r_iv->flags & MIN_EXCLUDED); if (flags) { res = tarval_cmp(l_iv->max, r_iv->min); if (res == ir_relation_less || res == ir_relation_equal) return tv_true; } res = tarval_cmp(l_iv->min, r_iv->max); /* [a, b] > [c, d] <==> a > d */ if (res == ir_relation_greater) return tv_false; /* if one border is excluded, a >= d is enough */ if ((l_iv->flags & MIN_EXCLUDED || r_iv->flags & MAX_EXCLUDED) && res == ir_relation_equal) return tv_false; break; case ir_relation_less_equal_greater: /* Hmm. if both are intervals, we can find an order */ return tv_true; default: return tarval_bad; } return tarval_bad; }
/* * Check, if the value of a node can be confirmed >= 0 or <= 0, * If the mode of the value did not honor signed zeros, else * check for >= 0 or < 0. */ ir_value_classify_sign classify_value_sign(ir_node *n) { ir_tarval *tv, *c; ir_mode *mode; ir_relation cmp, ncmp; int negate = 1; for (;;) { unsigned code = get_irn_opcode(n); switch (code) { case iro_Minus: negate *= -1; n = get_Minus_op(n); continue; case iro_Confirm: break; default: return value_classified_unknown; } break; } if (!is_Confirm(n)) return value_classified_unknown; tv = value_of(get_Confirm_bound(n)); if (tv == tarval_bad) return value_classified_unknown; mode = get_irn_mode(n); /* * We can handle only >=, >, <, <= cases. * We could handle == too, but this will be optimized into * a constant either. * * Note that for integer modes we have a slightly better * optimization possibilities, so we handle this * different. */ cmp = get_Confirm_relation(n); switch (cmp) { case ir_relation_less: /* * must be x < c <= 1 to be useful if integer mode and -0 = 0 * x < c <= 0 to be useful else */ case ir_relation_less_equal: /* * must be x <= c < 1 to be useful if integer mode and -0 = 0 * x <= c < 0 to be useful else */ c = mode_is_int(mode) && mode_honor_signed_zeros(mode) ? get_mode_one(mode) : get_mode_null(mode); ncmp = tarval_cmp(tv, c); if (ncmp == ir_relation_equal) ncmp = ir_relation_less_equal; if (cmp != (ncmp ^ ir_relation_equal)) return value_classified_unknown; /* yep, negative */ return value_classified_negative * negate; case ir_relation_greater_equal: /* * must be x >= c > -1 to be useful if integer mode * x >= c >= 0 to be useful else */ case ir_relation_greater: /* * must be x > c >= -1 to be useful if integer mode * x > c >= 0 to be useful else */ if (mode_is_int(mode)) { c = get_mode_minus_one(mode); ncmp = tarval_cmp(tv, c); if (ncmp == ir_relation_equal) ncmp = ir_relation_greater_equal; if (cmp != (ncmp ^ ir_relation_equal)) return value_classified_unknown; } else { c = get_mode_minus_one(mode); ncmp = tarval_cmp(tv, c); if (ncmp != ir_relation_equal && ncmp != ir_relation_greater) return value_classified_unknown; } /* yep, positive */ return value_classified_positive * negate; default: return value_classified_unknown; } }