enum value_range_type get_range_info (const_tree name, double_int *min, double_int *max) { gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name))); gcc_assert (min && max); range_info_def *ri = SSA_NAME_RANGE_INFO (name); /* Return VR_VARYING for SSA_NAMEs with NULL RANGE_INFO or SSA_NAMEs with integral types width > 2 * HOST_BITS_PER_WIDE_INT precision. */ if (!ri || (GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (name))) > 2 * HOST_BITS_PER_WIDE_INT)) return VR_VARYING; *min = ri->min; *max = ri->max; return SSA_NAME_RANGE_TYPE (name); }
void set_range_info (tree name, enum value_range_type range_type, double_int min, double_int 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); /* Allocate if not available. */ if (ri == NULL) { ri = ggc_alloc_cleared_range_info_def (); SSA_NAME_RANGE_INFO (name) = ri; ri->nonzero_bits = double_int::mask (TYPE_PRECISION (TREE_TYPE (name))); } /* Record the range type. */ if (SSA_NAME_RANGE_TYPE (name) != range_type) SSA_NAME_ANTI_RANGE_P (name) = (range_type == VR_ANTI_RANGE); /* Set the values. */ ri->min = min; ri->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); } }
tree duplicate_ssa_name_fn (struct function *fn, tree name, gimple stmt) { tree new_name = copy_ssa_name_fn (fn, name, stmt); if (POINTER_TYPE_P (TREE_TYPE (name))) { struct ptr_info_def *old_ptr_info = SSA_NAME_PTR_INFO (name); if (old_ptr_info) duplicate_ssa_name_ptr_info (new_name, old_ptr_info); } else { struct range_info_def *old_range_info = SSA_NAME_RANGE_INFO (name); if (old_range_info) duplicate_ssa_name_range_info (new_name, SSA_NAME_RANGE_TYPE (name), old_range_info); } return new_name; }
void 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) { size_t size = (sizeof (range_info_def) + trailing_wide_ints <3>::extra_size (precision)); ri = static_cast<range_info_def *> (ggc_internal_alloc (size)); ri->ints.set_precision (precision); SSA_NAME_RANGE_INFO (name) = ri; ri->set_nonzero_bits (wi::shwi (-1, precision)); } /* Record the range type. */ if (SSA_NAME_RANGE_TYPE (name) != range_type) SSA_NAME_ANTI_RANGE_P (name) = (range_type == VR_ANTI_RANGE); /* Set the values. */ 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) { 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)); } }
static bool fini_copy_prop (void) { unsigned i; /* Set the final copy-of value for each variable by traversing the copy-of chains. */ for (i = 1; i < num_ssa_names; i++) { tree var = ssa_name (i); if (!var || !copy_of[i].value || copy_of[i].value == var) continue; /* In theory the points-to solution of all members of the copy chain is their intersection. For now we do not bother to compute this but only make sure we do not lose points-to information completely by setting the points-to solution of the representative to the first solution we find if it doesn't have one already. */ if (copy_of[i].value != var && TREE_CODE (copy_of[i].value) == SSA_NAME) { basic_block copy_of_bb = gimple_bb (SSA_NAME_DEF_STMT (copy_of[i].value)); basic_block var_bb = gimple_bb (SSA_NAME_DEF_STMT (var)); if (POINTER_TYPE_P (TREE_TYPE (var)) && SSA_NAME_PTR_INFO (var) && !SSA_NAME_PTR_INFO (copy_of[i].value)) { duplicate_ssa_name_ptr_info (copy_of[i].value, SSA_NAME_PTR_INFO (var)); /* Points-to information is cfg insensitive, but alignment info might be cfg sensitive, if it e.g. is derived from VRP derived non-zero bits. So, do not copy alignment info if the two SSA_NAMEs aren't defined in the same basic block. */ if (var_bb != copy_of_bb) mark_ptr_info_alignment_unknown (SSA_NAME_PTR_INFO (copy_of[i].value)); } else if (!POINTER_TYPE_P (TREE_TYPE (var)) && SSA_NAME_RANGE_INFO (var) && !SSA_NAME_RANGE_INFO (copy_of[i].value) && var_bb == copy_of_bb) duplicate_ssa_name_range_info (copy_of[i].value, SSA_NAME_RANGE_TYPE (var), SSA_NAME_RANGE_INFO (var)); } } bool changed = substitute_and_fold (get_value, NULL, true); if (changed) { free_numbers_of_iterations_estimates (); if (scev_initialized_p ()) scev_reset (); } free (copy_of); return changed; }