/** * 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; }
static void check_mode(ir_mode *mode) { ir_tarval *zero = get_mode_null(mode); ir_tarval *minus_zero = tarval_neg(zero); ir_tarval *min = get_mode_min(mode); ir_tarval *max = get_mode_max(mode); ir_tarval *inf = get_mode_infinite(mode); ir_tarval *minus_inf = tarval_neg(inf); ir_tarval *one = get_mode_one(mode); ir_tarval *minus_one = tarval_neg(one); /* some random arithmetics */ ir_tarval *int_zero = get_mode_null(mode_Is); ir_tarval *int_one = get_mode_one(mode_Is); ir_tarval *int_minus_one = get_mode_all_one(mode_Is); ir_tarval *int_min = get_mode_min(mode_Is); ir_tarval *int_max = get_mode_max(mode_Is); assert(tarval_convert_to(zero, mode_Is) == int_zero); assert(tarval_convert_to(minus_zero, mode_Is) == int_zero); assert(tarval_convert_to(one, mode_Is) == int_one); assert(tarval_convert_to(minus_one, mode_Is) == int_minus_one); assert(tarval_convert_to(min, mode_Is) == int_min); assert(tarval_convert_to(max, mode_Is) == int_max); assert(tarval_convert_to(inf, mode_Is) == int_max); assert(tarval_convert_to(minus_inf, mode_Is) == int_min); static const char *const ints[] = { "0", "1", "-1", "12345", "2", "4", "8", "16", "32", "64", "128", "256", "512", "1024", "2048", "127", "2047" }; for (unsigned i = 0; i < ARRAY_SIZE(ints); ++i) { const char *str = ints[i]; ir_tarval *flt = new_tarval_from_str(str, strlen(str), mode); ir_tarval *intt = new_tarval_from_str(str, strlen(str), mode_Is); assert(tarval_convert_to(flt, mode_Is) == intt); assert(tarval_convert_to(intt, mode) == flt); } }
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; }
/** * construct an interval from a value * * @return the filled interval or NULL if no interval * can be created (happens only on floating point */ static interval_t *get_interval_from_tv(interval_t *iv, ir_tarval *tv) { ir_mode *mode = get_tarval_mode(tv); if (tv == tarval_bad) { if (mode_is_float(mode)) { /* NaN could be included which we cannot handle */ iv->min = tarval_bad; iv->max = tarval_bad; iv->flags = MIN_EXCLUDED | MAX_EXCLUDED; return NULL; } else { /* [-oo, +oo] */ iv->min = get_mode_min(mode); iv->max = get_mode_max(mode); iv->flags = MIN_INCLUDED | MAX_INCLUDED; return iv; } } if (mode_is_float(mode)) { if (tv == get_mode_NAN(mode)) { /* arg, we cannot handle NaN's. */ iv->min = tarval_bad; iv->max = tarval_bad; iv->flags = MIN_EXCLUDED | MAX_EXCLUDED; return NULL; } } /* [tv, tv] */ iv->min = tv; iv->max = tv; iv->flags = MIN_INCLUDED | MAX_INCLUDED; return iv; }
/** * construct an interval from a Confirm * * @param iv an empty interval, will be filled * @param bound the bound value * @param relation the Confirm compare relation * * @return the filled interval or NULL if no interval * can be created (happens only on floating point */ static interval_t *get_interval(interval_t *iv, ir_node *bound, ir_relation relation) { ir_mode *mode = get_irn_mode(bound); ir_tarval *tv = value_of(bound); if (tv == tarval_bad) { /* There is nothing we could do here. For integer * modes we could return [-oo, +oo], but there is * nothing we could deduct from such an interval. * So, speed things up and return unknown. */ iv->min = tarval_bad; iv->max = tarval_bad; iv->flags = MIN_EXCLUDED | MAX_EXCLUDED; return NULL; } if (mode_is_float(mode)) { if (tv == get_mode_NAN(mode)) { /* arg, we cannot handle NaN's. */ iv->min = tarval_bad; iv->max = tarval_bad; iv->flags = MIN_EXCLUDED | MAX_EXCLUDED; return NULL; } } /* check which side is known */ switch (relation) { case ir_relation_equal: /* [tv, tv] */ iv->min = iv->max = tv; iv->flags = MIN_INCLUDED | MAX_INCLUDED; break; case ir_relation_less_equal: /* [-oo, tv] */ iv->min = get_mode_min(mode); iv->max = tv; iv->flags = MIN_INCLUDED | MAX_INCLUDED; break; case ir_relation_less: /* [-oo, tv) */ iv->min = get_mode_min(mode); iv->max = tv; iv->flags = MIN_INCLUDED | MAX_EXCLUDED; break; case ir_relation_greater: /* (tv, +oo] */ iv->min = tv; iv->max = get_mode_max(mode); iv->flags = MIN_EXCLUDED | MAX_INCLUDED; break; case ir_relation_greater_equal: /* [tv, +oo] */ iv->min = tv; iv->max = get_mode_max(mode); iv->flags = MIN_INCLUDED | MAX_INCLUDED; break; case ir_relation_less_equal_greater: /* * Ordered means, that at least neither * our bound nor our value ara NaN's */ /* [-oo, +oo] */ iv->min = get_mode_min(mode); iv->max = get_mode_max(mode); iv->flags = MIN_INCLUDED | MAX_INCLUDED; break; default: /* * We do not handle UNORDERED, as a NaN * could be included in the interval. */ iv->min = tarval_bad; iv->max = tarval_bad; iv->flags = MIN_EXCLUDED | MAX_EXCLUDED; return NULL; } if (iv->min != tarval_bad && iv->max != tarval_bad) return iv; return NULL; }