void 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, TYPE_MIN_VALUE (TREE_TYPE (name)), TYPE_MAX_VALUE (TREE_TYPE (name))); range_info_def *ri = SSA_NAME_RANGE_INFO (name); ri->set_nonzero_bits (mask); }
void set_nonzero_bits (tree name, double_int 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)))); range_info_def *ri = SSA_NAME_RANGE_INFO (name); ri->nonzero_bits = mask & double_int::mask (TYPE_PRECISION (TREE_TYPE (name))); }
/* Creates a duplicate of the range_info_def at RANGE_INFO for use by the SSA name NAME. */ void duplicate_ssa_name_range_info (tree name, struct range_info_def *range_info) { struct range_info_def *new_range_info; gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name))); gcc_assert (!SSA_NAME_RANGE_INFO (name)); if (!range_info) return; new_range_info = ggc_alloc_range_info_def (); *new_range_info = *range_info; SSA_NAME_RANGE_INFO (name) = new_range_info; }
enum value_range_type get_range_info (tree name, double_int *min, double_int *max) { enum value_range_type range_type; 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; /* If min > max, it is VR_ANTI_RANGE. */ if (ri->min.cmp (ri->max, TYPE_UNSIGNED (TREE_TYPE (name))) == 1) { /* VR_ANTI_RANGE ~[min, max] is encoded as [max + 1, min - 1]. */ range_type = VR_ANTI_RANGE; *min = ri->max + double_int_one; *max = ri->min - double_int_one; } else { /* Otherwise (when min <= max), it is VR_RANGE. */ range_type = VR_RANGE; *min = ri->min; *max = ri->max; } return range_type; }
void set_range_info (tree name, double_int min, double_int max) { gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name))); 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; } /* Set the values. */ ri->min = min; ri->max = max; }
tree make_ssa_name_fn (struct function *fn, tree var, gimple stmt) { tree t; use_operand_p imm; gcc_assert (TREE_CODE (var) == VAR_DECL || TREE_CODE (var) == PARM_DECL || TREE_CODE (var) == RESULT_DECL || (TYPE_P (var) && is_gimple_reg_type (var))); /* If our free list has an element, then use it. */ if (!vec_safe_is_empty (FREE_SSANAMES (fn))) { t = FREE_SSANAMES (fn)->pop (); if (GATHER_STATISTICS) ssa_name_nodes_reused++; /* The node was cleared out when we put it on the free list, so there is no need to do so again here. */ gcc_assert (ssa_name (SSA_NAME_VERSION (t)) == NULL); (*SSANAMES (fn))[SSA_NAME_VERSION (t)] = t; } else { t = make_node (SSA_NAME); SSA_NAME_VERSION (t) = SSANAMES (fn)->length (); vec_safe_push (SSANAMES (fn), t); if (GATHER_STATISTICS) ssa_name_nodes_created++; } if (TYPE_P (var)) { TREE_TYPE (t) = var; SET_SSA_NAME_VAR_OR_IDENTIFIER (t, NULL_TREE); } else { TREE_TYPE (t) = TREE_TYPE (var); SET_SSA_NAME_VAR_OR_IDENTIFIER (t, var); } SSA_NAME_DEF_STMT (t) = stmt; if (POINTER_TYPE_P (TREE_TYPE (t))) SSA_NAME_PTR_INFO (t) = NULL; else SSA_NAME_RANGE_INFO (t) = NULL; SSA_NAME_IN_FREE_LIST (t) = 0; SSA_NAME_IS_DEFAULT_DEF (t) = 0; imm = &(SSA_NAME_IMM_USE_NODE (t)); imm->use = NULL; imm->prev = imm; imm->next = imm; imm->loc.ssa_name = t; return t; }
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); } }
/* Creates a duplicate of the range_info_def at RANGE_INFO of type RANGE_TYPE for use by the SSA name NAME. */ void duplicate_ssa_name_range_info (tree name, enum value_range_type range_type, struct range_info_def *range_info) { struct range_info_def *new_range_info; gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name))); gcc_assert (!SSA_NAME_RANGE_INFO (name)); gcc_assert (!SSA_NAME_ANTI_RANGE_P (name)); if (!range_info) return; new_range_info = ggc_alloc_range_info_def (); *new_range_info = *range_info; gcc_assert (range_type == VR_RANGE || range_type == VR_ANTI_RANGE); SSA_NAME_ANTI_RANGE_P (name) = (range_type == VR_ANTI_RANGE); SSA_NAME_RANGE_INFO (name) = new_range_info; }
void reset_flow_sensitive_info (tree name) { if (POINTER_TYPE_P (TREE_TYPE (name))) { /* points-to info is not flow-sensitive. */ if (SSA_NAME_PTR_INFO (name)) mark_ptr_info_alignment_unknown (SSA_NAME_PTR_INFO (name)); } else SSA_NAME_RANGE_INFO (name) = NULL; }
/* Creates a duplicate of the range_info_def at RANGE_INFO of type RANGE_TYPE for use by the SSA name NAME. */ void duplicate_ssa_name_range_info (tree name, enum value_range_type range_type, struct range_info_def *range_info) { struct range_info_def *new_range_info; gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name))); gcc_assert (!SSA_NAME_RANGE_INFO (name)); gcc_assert (!SSA_NAME_ANTI_RANGE_P (name)); if (!range_info) return; 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 = static_cast<range_info_def *> (ggc_internal_alloc (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); SSA_NAME_RANGE_INFO (name) = new_range_info; }
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)); } }
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); }
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) return wi::shwi (-(HOST_WIDE_INT) pi->align | (HOST_WIDE_INT) pi->misalign, precision); return wi::shwi (-1, precision); } range_info_def *ri = SSA_NAME_RANGE_INFO (name); if (!ri) return wi::shwi (-1, precision); return ri->get_nonzero_bits (); }
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, old_range_info); } return new_name; }
double_int get_nonzero_bits (const_tree 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; } 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; return ri->nonzero_bits; }
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; }