diff options
Diffstat (limited to 'gcc/tree-ssanames.c')
-rw-r--r-- | gcc/tree-ssanames.c | 77 |
1 files changed, 35 insertions, 42 deletions
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c index 4e576977235..be358e1d97d 100644 --- a/gcc/tree-ssanames.c +++ b/gcc/tree-ssanames.c @@ -186,19 +186,23 @@ make_ssa_name_fn (struct function *fn, tree var, gimple stmt) /* Store range information RANGE_TYPE, MIN, and MAX to tree ssa_name NAME. */ void -set_range_info (tree name, enum value_range_type range_type, double_int min, - double_int max) +set_range_info (tree name, enum value_range_type range_type, + const wide_int_ref &min, const wide_int_ref &max) { gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name))); gcc_assert (range_type == VR_RANGE || range_type == VR_ANTI_RANGE); range_info_def *ri = SSA_NAME_RANGE_INFO (name); + unsigned int precision = TYPE_PRECISION (TREE_TYPE (name)); /* Allocate if not available. */ if (ri == NULL) { - ri = ggc_alloc_cleared_range_info_def (); + size_t size = (sizeof (range_info_def) + + trailing_wide_ints <3>::extra_size (precision)); + ri = ggc_alloc_range_info_def (size); + ri->ints.set_precision (precision); SSA_NAME_RANGE_INFO (name) = ri; - ri->nonzero_bits = double_int::mask (TYPE_PRECISION (TREE_TYPE (name))); + ri->set_nonzero_bits (wi::shwi (-1, precision)); } /* Record the range type. */ @@ -206,25 +210,16 @@ set_range_info (tree name, enum value_range_type range_type, double_int min, SSA_NAME_ANTI_RANGE_P (name) = (range_type == VR_ANTI_RANGE); /* Set the values. */ - ri->min = min; - ri->max = max; + ri->set_min (min); + ri->set_max (max); /* If it is a range, try to improve nonzero_bits from the min/max. */ if (range_type == VR_RANGE) { - int prec = TYPE_PRECISION (TREE_TYPE (name)); - double_int xorv; - - min = min.zext (prec); - max = max.zext (prec); - xorv = min ^ max; - if (xorv.high) - xorv = double_int::mask (2 * HOST_BITS_PER_WIDE_INT - - clz_hwi (xorv.high)); - else if (xorv.low) - xorv = double_int::mask (HOST_BITS_PER_WIDE_INT - - clz_hwi (xorv.low)); - ri->nonzero_bits = ri->nonzero_bits & (min | xorv); + wide_int xorv = ri->get_min () ^ ri->get_max (); + if (xorv != 0) + xorv = wi::mask (precision - wi::clz (xorv), false, precision); + ri->set_nonzero_bits (ri->get_nonzero_bits () & (ri->get_min () | xorv)); } } @@ -234,7 +229,7 @@ set_range_info (tree name, enum value_range_type range_type, double_int min, is used to determine if MIN and MAX are valid values. */ enum value_range_type -get_range_info (const_tree name, double_int *min, double_int *max) +get_range_info (const_tree name, wide_int *min, wide_int *max) { gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name))); gcc_assert (min && max); @@ -246,50 +241,45 @@ get_range_info (const_tree name, double_int *min, double_int *max) > 2 * HOST_BITS_PER_WIDE_INT)) return VR_VARYING; - *min = ri->min; - *max = ri->max; + *min = ri->get_min (); + *max = ri->get_max (); return SSA_NAME_RANGE_TYPE (name); } /* Change non-zero bits bitmask of NAME. */ void -set_nonzero_bits (tree name, double_int mask) +set_nonzero_bits (tree name, const wide_int_ref &mask) { gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name))); if (SSA_NAME_RANGE_INFO (name) == NULL) set_range_info (name, VR_RANGE, - tree_to_double_int (TYPE_MIN_VALUE (TREE_TYPE (name))), - tree_to_double_int (TYPE_MAX_VALUE (TREE_TYPE (name)))); + TYPE_MIN_VALUE (TREE_TYPE (name)), + TYPE_MAX_VALUE (TREE_TYPE (name))); range_info_def *ri = SSA_NAME_RANGE_INFO (name); - ri->nonzero_bits - = mask & double_int::mask (TYPE_PRECISION (TREE_TYPE (name))); + ri->set_nonzero_bits (mask); } -/* Return a double_int with potentially non-zero bits in SSA_NAME - NAME, or double_int_minus_one if unknown. */ +/* Return a widest_int with potentially non-zero bits in SSA_NAME + NAME, or -1 if unknown. */ -double_int +wide_int get_nonzero_bits (const_tree name) { + unsigned int precision = TYPE_PRECISION (TREE_TYPE (name)); if (POINTER_TYPE_P (TREE_TYPE (name))) { struct ptr_info_def *pi = SSA_NAME_PTR_INFO (name); if (pi && pi->align) - { - double_int al = double_int::from_uhwi (pi->align - 1); - return ((double_int::mask (TYPE_PRECISION (TREE_TYPE (name))) & ~al) - | double_int::from_uhwi (pi->misalign)); - } - return double_int_minus_one; + return wi::shwi (-(int) pi->align | pi->misalign, precision); + return wi::shwi (-1, precision); } range_info_def *ri = SSA_NAME_RANGE_INFO (name); - if (!ri || (GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (name))) - > 2 * HOST_BITS_PER_WIDE_INT)) - return double_int_minus_one; + if (!ri) + return wi::shwi (-1, precision); - return ri->nonzero_bits; + return ri->get_nonzero_bits (); } /* We no longer need the SSA_NAME expression VAR, release it so that @@ -502,8 +492,11 @@ duplicate_ssa_name_range_info (tree name, enum value_range_type range_type, if (!range_info) return; - new_range_info = ggc_alloc_range_info_def (); - *new_range_info = *range_info; + unsigned int precision = TYPE_PRECISION (TREE_TYPE (name)); + size_t size = (sizeof (range_info_def) + + trailing_wide_ints <3>::extra_size (precision)); + new_range_info = ggc_alloc_range_info_def (size); + memcpy (new_range_info, range_info, size); gcc_assert (range_type == VR_RANGE || range_type == VR_ANTI_RANGE); SSA_NAME_ANTI_RANGE_P (name) = (range_type == VR_ANTI_RANGE); |