diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/gimple-range.cc | 30 | ||||
-rw-r--r-- | gcc/tree-core.h | 13 | ||||
-rw-r--r-- | gcc/tree-ssa-dom.cc | 2 | ||||
-rw-r--r-- | gcc/tree-ssanames.cc | 240 | ||||
-rw-r--r-- | gcc/tree-ssanames.h | 12 | ||||
-rw-r--r-- | gcc/tree-vrp.cc | 22 | ||||
-rw-r--r-- | gcc/tree.h | 8 | ||||
-rw-r--r-- | gcc/value-query.cc | 54 | ||||
-rw-r--r-- | gcc/value-query.h | 1 | ||||
-rw-r--r-- | gcc/value-range-storage.cc | 4 |
10 files changed, 149 insertions, 237 deletions
diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc index 3a9f0b0..7ac4830 100644 --- a/gcc/gimple-range.cc +++ b/gcc/gimple-range.cc @@ -468,22 +468,12 @@ gimple_ranger::register_inferred_ranges (gimple *s) { Value_Range tmp (TREE_TYPE (lhs)); if (range_of_stmt (tmp, s, lhs) && !tmp.varying_p () - && update_global_range (tmp, lhs) && dump_file) + && set_range_info (lhs, tmp) && dump_file) { - // ?? This section should be adjusted when non-iranges can - // be exported. For now, the only way update_global_range - // above can succeed is with an irange so this is safe. - value_range vr = as_a <irange> (tmp); fprintf (dump_file, "Global Exported: "); print_generic_expr (dump_file, lhs, TDF_SLIM); fprintf (dump_file, " = "); - vr.dump (dump_file); - int_range_max same = vr; - if (same != as_a <irange> (tmp)) - { - fprintf (dump_file, " ... irange was : "); - tmp.dump (dump_file); - } + tmp.dump (dump_file); fputc ('\n', dump_file); } } @@ -509,7 +499,7 @@ gimple_ranger::export_global_ranges () && m_cache.get_global_range (r, name) && !r.varying_p()) { - bool updated = update_global_range (r, name); + bool updated = set_range_info (name, r); if (!updated || !dump_file) continue; @@ -522,22 +512,10 @@ gimple_ranger::export_global_ranges () print_header = false; } - if (!irange::supports_p (TREE_TYPE (name))) - continue; - - vrange &v = r; - value_range vr = as_a <irange> (v); print_generic_expr (dump_file, name , TDF_SLIM); fprintf (dump_file, " : "); - vr.dump (dump_file); + r.dump (dump_file); fprintf (dump_file, "\n"); - int_range_max same = vr; - if (same != as_a <irange> (v)) - { - fprintf (dump_file, " irange : "); - r.dump (dump_file); - fprintf (dump_file, "\n"); - } } } } diff --git a/gcc/tree-core.h b/gcc/tree-core.h index ab5fa01..ea9f281 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -33,7 +33,7 @@ struct function; struct real_value; struct fixed_value; struct ptr_info_def; -struct range_info_def; +struct irange_storage_slot; struct die_struct; @@ -1194,9 +1194,6 @@ struct GTY(()) tree_base { TRANSACTION_EXPR_OUTER in TRANSACTION_EXPR - SSA_NAME_ANTI_RANGE_P in - SSA_NAME - MUST_TAIL_CALL in CALL_EXPR @@ -1594,8 +1591,12 @@ struct GTY(()) tree_ssa_name { union ssa_name_info_type { /* Pointer attributes used for alias analysis. */ struct GTY ((tag ("0"))) ptr_info_def *ptr_info; - /* Value range attributes used for zero/sign extension elimination. */ - struct GTY ((tag ("1"))) range_info_def *range_info; + /* This holds any range info supported by ranger (except ptr_info + above) and is managed by vrange_storage. */ + void * GTY ((skip)) range_info; + /* GTY tag when the range in the range_info slot above satisfies + irange::supports_type_p. */ + struct GTY ((tag ("1"))) irange_storage_slot *irange_info; } GTY ((desc ("%1.typed.type ?" \ "!POINTER_TYPE_P (TREE_TYPE ((tree)&%1)) : 2"))) info; diff --git a/gcc/tree-ssa-dom.cc b/gcc/tree-ssa-dom.cc index 2bc2c3d..43acc75 100644 --- a/gcc/tree-ssa-dom.cc +++ b/gcc/tree-ssa-dom.cc @@ -1255,7 +1255,7 @@ dom_opt_dom_walker::set_global_ranges_from_unreachable_edges (basic_block bb) && !r.varying_p () && !r.undefined_p ()) { - update_global_range (r, name); + set_range_info (name, r); maybe_set_nonzero_bits (pred_e, name); } } diff --git a/gcc/tree-ssanames.cc b/gcc/tree-ssanames.cc index bc22ece..9389454 100644 --- a/gcc/tree-ssanames.cc +++ b/gcc/tree-ssanames.cc @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see #include "cfgloop.h" #include "tree-scalar-evolution.h" #include "value-query.h" +#include "value-range-storage.h" /* Rewriting a function into SSA form can create a huge number of SSA_NAMEs, many of which may be thrown away shortly after their creation if jumps @@ -71,6 +72,74 @@ unsigned int ssa_name_nodes_created; #define FREE_SSANAMES(fun) (fun)->gimple_df->free_ssanames #define FREE_SSANAMES_QUEUE(fun) (fun)->gimple_df->free_ssanames_queue +static ggc_vrange_allocator ggc_allocator; +static vrange_storage vstore (&ggc_allocator); + +/* Return TRUE if NAME has global range info. */ + +inline bool +range_info_p (const_tree name) +{ + return SSA_NAME_RANGE_INFO (name); +} + +/* Return TRUE if R fits in the global range of NAME. */ + +inline bool +range_info_fits_p (tree name, const vrange &r) +{ + gcc_checking_assert (range_info_p (name)); + void *mem = SSA_NAME_RANGE_INFO (name); + return vrange_storage::fits_p (mem, r); +} + +/* Allocate a new global range for NAME and set it to R. Return the + allocation slot. */ + +inline void * +range_info_alloc (tree name, const vrange &r) +{ + void *mem = vstore.alloc_slot (r); + SSA_NAME_RANGE_INFO (name) = mem; + return mem; +} + +/* Free storage allocated for the global range for NAME. */ + +inline void +range_info_free (tree name) +{ + void *mem = SSA_NAME_RANGE_INFO (name); + vstore.free (mem); +} + +/* Return the global range for NAME in R. */ + +inline void +range_info_get_range (tree name, vrange &r) +{ + vstore.get_vrange (SSA_NAME_RANGE_INFO (name), r, TREE_TYPE (name)); +} + +/* Set the global range for NAME from R. Return TRUE if successfull, + or FALSE if we can't set a range of NAME's type. */ + +inline bool +range_info_set_range (tree name, const vrange &r) +{ + if (!range_info_p (name) || !range_info_fits_p (name, r)) + { + if (range_info_p (name)) + range_info_free (name); + + return range_info_alloc (name, r); + } + else + { + vstore.set_vrange (SSA_NAME_RANGE_INFO (name), r); + return true; + } +} /* Initialize management of SSA_NAMEs to default SIZE. If SIZE is zero use default. */ @@ -343,94 +412,38 @@ make_ssa_name_fn (struct function *fn, tree var, gimple *stmt, return t; } -/* Helper function for set_range_info. - - Store range information RANGE_TYPE, MIN, and MAX to tree ssa_name - NAME. */ - -void -set_range_info_raw (tree name, enum value_range_kind 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); +/* Update the range information for NAME, intersecting into an existing + range if applicable. Return TRUE if the range was updated. */ - /* 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)); - } -} - -/* Store range information RANGE_TYPE, MIN, and MAX to tree ssa_name - NAME while making sure we don't store useless range info. */ - -static void -set_range_info (tree name, enum value_range_kind range_type, - const wide_int_ref &min, const wide_int_ref &max) +bool +set_range_info (tree name, const vrange &r) { - gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name))); + if (r.undefined_p () || r.varying_p ()) + return false; tree type = TREE_TYPE (name); - if (range_type == VR_VARYING) + if (POINTER_TYPE_P (type)) { - /* SSA_NAME_RANGE_TYPE can only hold a VR_RANGE or - VR_ANTI_RANGE. Denormalize VR_VARYING to VR_RANGE. */ - range_type = VR_RANGE; - gcc_checking_assert (min == wi::min_value (type)); - gcc_checking_assert (max == wi::max_value (type)); - } - - /* A range of the entire domain is really no range at all. */ - if (min == wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type)) - && max == wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type))) - { - range_info_def *ri = SSA_NAME_RANGE_INFO (name); - if (ri == NULL) - return; - if (ri->get_nonzero_bits () == -1) + if (r.nonzero_p ()) { - ggc_free (ri); - SSA_NAME_RANGE_INFO (name) = NULL; - return; + set_ptr_nonnull (name); + return true; } + return false; } - set_range_info_raw (name, range_type, min, max); -} - -/* Store range information for NAME from a value_range. */ + /* If a global range already exists, incorporate it. */ + if (range_info_p (name)) + { + Value_Range tmp (type); + range_info_get_range (name, tmp); + tmp.intersect (r); + if (tmp.undefined_p ()) + return false; -void -set_range_info (tree name, const value_range &vr) -{ - wide_int min = wi::to_wide (vr.min ()); - wide_int max = wi::to_wide (vr.max ()); - set_range_info (name, vr.kind (), min, max); + return range_info_set_range (name, tmp); + } + return range_info_set_range (name, r); } /* Set nonnull attribute to pointer NAME. */ @@ -443,22 +456,16 @@ set_ptr_nonnull (tree name) pi->pt.null = 0; } -/* Change non-zero bits bitmask of NAME. */ +/* Update the non-zero bits bitmask of NAME. */ 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) - { - if (mask == -1) - return; - set_range_info_raw (name, VR_RANGE, - wi::to_wide (TYPE_MIN_VALUE (TREE_TYPE (name))), - wi::to_wide (TYPE_MAX_VALUE (TREE_TYPE (name)))); - } - range_info_def *ri = SSA_NAME_RANGE_INFO (name); - ri->set_nonzero_bits (mask); + + int_range<2> r (TREE_TYPE (name)); + r.set_nonzero_bits (mask); + set_range_info (name, r); } /* Return a widest_int with potentially non-zero bits in SSA_NAME @@ -482,10 +489,15 @@ get_nonzero_bits (const_tree name) return wi::shwi (-1, precision); } - range_info_def *ri = SSA_NAME_RANGE_INFO (name); - if (!ri) + if (!range_info_p (name)) return wi::shwi (-1, precision); + /* Optimization to get at the nonzero bits because we know the + storage type. This saves us measurable time compared to going + through vrange_storage. */ + gcc_checking_assert (irange::supports_p (TREE_TYPE (name))); + irange_storage_slot *ri + = static_cast <irange_storage_slot *> (SSA_NAME_RANGE_INFO (name)); return ri->get_nonzero_bits (); } @@ -727,38 +739,18 @@ duplicate_ssa_name_ptr_info (tree name, struct ptr_info_def *ptr_info) SSA_NAME_PTR_INFO (name) = new_ptr_info; } -/* Creates a duplicate of the range_info_def at RANGE_INFO of type - RANGE_TYPE for use by the SSA name NAME. */ -static void -duplicate_ssa_name_range_info (tree name, enum value_range_kind 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)); - - 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 duplicate_ssa_name_range_info (tree name, tree src) { gcc_checking_assert (!POINTER_TYPE_P (TREE_TYPE (src))); - duplicate_ssa_name_range_info (name, - SSA_NAME_RANGE_TYPE (src), - SSA_NAME_RANGE_INFO (src)); + gcc_checking_assert (!range_info_p (name)); + + if (range_info_p (src)) + { + Value_Range src_range (TREE_TYPE (src)); + range_info_get_range (src, src_range); + range_info_set_range (name, src_range); + } } @@ -776,14 +768,8 @@ duplicate_ssa_name_fn (struct function *fn, tree name, gimple *stmt) 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); - } + else if (range_info_p (name)) + duplicate_ssa_name_range_info (new_name, name); return new_name; } diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h index 8c419b1..ce10af9 100644 --- a/gcc/tree-ssanames.h +++ b/gcc/tree-ssanames.h @@ -45,16 +45,6 @@ struct GTY(()) ptr_info_def unsigned int misalign; }; -/* Value range information for SSA_NAMEs representing non-pointer variables. */ - -struct GTY ((variable_size)) range_info_def { - /* Minimum, maximum and nonzero bits. */ - TRAILING_WIDE_INT_ACCESSOR (min, ints, 0) - TRAILING_WIDE_INT_ACCESSOR (max, ints, 1) - TRAILING_WIDE_INT_ACCESSOR (nonzero_bits, ints, 2) - trailing_wide_ints <3> ints; -}; - #define SSANAMES(fun) (fun)->gimple_df->ssa_names #define DEFAULT_DEFS(fun) (fun)->gimple_df->default_defs @@ -67,7 +57,7 @@ struct GTY ((variable_size)) range_info_def { if (VAR) /* Sets the value range to SSA. */ -extern void set_range_info (tree, const value_range &); +extern bool set_range_info (tree, const vrange &); extern void set_nonzero_bits (tree, const wide_int_ref &); extern wide_int get_nonzero_bits (const_tree); extern bool ssa_name_has_boolean_range (tree); diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc index ed881be..c3030a1 100644 --- a/gcc/tree-vrp.cc +++ b/gcc/tree-vrp.cc @@ -3739,16 +3739,18 @@ vrp_asserts::remove_range_assertions () && all_imm_uses_in_stmt_or_feed_cond (var, stmt, single_pred (bb))) { - /* We could use duplicate_ssa_name_range_info here - instead of peeking inside SSA_NAME_RANGE_INFO, - but the aforementioned asserts that the - destination has no global range. This is - slated for removal anyhow. */ - value_range r (TREE_TYPE (lhs), - SSA_NAME_RANGE_INFO (lhs)->get_min (), - SSA_NAME_RANGE_INFO (lhs)->get_max (), - SSA_NAME_RANGE_TYPE (lhs)); - set_range_info (var, r); + if (SSA_NAME_RANGE_INFO (var)) + { + /* ?? This is a minor wart exposing the + internals of SSA_NAME_RANGE_INFO in order + to maintain existing behavior. This is + because duplicate_ssa_name_range_info below + needs a NULL destination range. This is + all slated for removal... */ + ggc_free (SSA_NAME_RANGE_INFO (var)); + SSA_NAME_RANGE_INFO (var) = NULL; + } + duplicate_ssa_name_range_info (var, lhs); maybe_set_nonzero_bits (single_pred_edge (bb), var); } } @@ -2030,14 +2030,6 @@ class auto_suppress_location_wrappers #define SSA_NAME_PTR_INFO(N) \ SSA_NAME_CHECK (N)->ssa_name.info.ptr_info -/* True if SSA_NAME_RANGE_INFO describes an anti-range. */ -#define SSA_NAME_ANTI_RANGE_P(N) \ - SSA_NAME_CHECK (N)->base.static_flag - -/* The type of range described by SSA_NAME_RANGE_INFO. */ -#define SSA_NAME_RANGE_TYPE(N) \ - (SSA_NAME_ANTI_RANGE_P (N) ? VR_ANTI_RANGE : VR_RANGE) - /* Value range info attributes for SSA_NAMEs of non pointer-type variables. */ #define SSA_NAME_RANGE_INFO(N) \ SSA_NAME_CHECK (N)->ssa_name.info.range_info diff --git a/gcc/value-query.cc b/gcc/value-query.cc index 1d7541c..51911bd 100644 --- a/gcc/value-query.cc +++ b/gcc/value-query.cc @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see #include "value-query.h" #include "alloc-pool.h" #include "gimple-range.h" +#include "value-range-storage.h" // value_query default methods. @@ -271,13 +272,13 @@ range_query::get_tree_range (vrange &r, tree expr, gimple *stmt) // Return the range for NAME from SSA_NAME_RANGE_INFO. static inline void -get_ssa_name_range_info (irange &r, const_tree name) +get_ssa_name_range_info (vrange &r, const_tree name) { tree type = TREE_TYPE (name); gcc_checking_assert (!POINTER_TYPE_P (type)); gcc_checking_assert (TREE_CODE (name) == SSA_NAME); - range_info_def *ri = SSA_NAME_RANGE_INFO (name); + void *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. @@ -285,9 +286,10 @@ get_ssa_name_range_info (irange &r, const_tree name) > 2 * HOST_BITS_PER_WIDE_INT)) r.set_varying (type); else - r.set (wide_int_to_tree (type, ri->get_min ()), - wide_int_to_tree (type, ri->get_max ()), - SSA_NAME_RANGE_TYPE (name)); + { + vrange_storage vstore (NULL); + vstore.get_vrange (ri, r, TREE_TYPE (name)); + } } // Return nonnull attribute of pointer NAME from SSA_NAME_PTR_INFO. @@ -311,43 +313,6 @@ get_ssa_name_ptr_info_nonnull (const_tree name) } // Update the global range for NAME into the SSA_RANGE_NAME_INFO and -// SSA_NAME_PTR_INFO fields. Return TRUE if the range for NAME was -// updated. - -bool -update_global_range (vrange &r, tree name) -{ - tree type = TREE_TYPE (name); - - if (r.undefined_p () || r.varying_p ()) - return false; - - if (INTEGRAL_TYPE_P (type)) - { - // If a global range already exists, incorporate it. - if (SSA_NAME_RANGE_INFO (name)) - { - value_range glob; - get_ssa_name_range_info (glob, name); - r.intersect (glob); - } - if (r.undefined_p ()) - return false; - - set_range_info (name, as_a <irange> (r)); - return true; - } - else if (POINTER_TYPE_P (type)) - { - if (r.nonzero_p ()) - { - set_ptr_nonnull (name); - return true; - } - } - return false; -} - // Return the legacy global range for NAME if it has one, otherwise // return VARYING. @@ -372,7 +337,7 @@ get_range_global (vrange &r, tree name) r.set_nonzero (type); else if (INTEGRAL_TYPE_P (type)) { - get_ssa_name_range_info (as_a <irange> (r), name); + get_ssa_name_range_info (r, name); if (r.undefined_p ()) r.set_varying (type); } @@ -387,8 +352,7 @@ get_range_global (vrange &r, tree name) } else if (!POINTER_TYPE_P (type) && SSA_NAME_RANGE_INFO (name)) { - gcc_checking_assert (irange::supports_p (TREE_TYPE (name))); - get_ssa_name_range_info (as_a <irange> (r), name); + get_ssa_name_range_info (r, name); if (r.undefined_p ()) r.set_varying (type); } diff --git a/gcc/value-query.h b/gcc/value-query.h index 280e47e..fc638eb 100644 --- a/gcc/value-query.h +++ b/gcc/value-query.h @@ -144,6 +144,5 @@ get_range_query (const struct function *fun) } extern void gimple_range_global (vrange &v, tree name); -extern bool update_global_range (vrange &v, tree name); #endif // GCC_QUERY_H diff --git a/gcc/value-range-storage.cc b/gcc/value-range-storage.cc index ac62bfa..8b5ab54 100644 --- a/gcc/value-range-storage.cc +++ b/gcc/value-range-storage.cc @@ -30,7 +30,8 @@ along with GCC; see the file COPYING3. If not see #include "gimple-range.h" #include "value-range-storage.h" -// Return a newly allocated slot holding R. +// Return a newly allocated slot holding R, or NULL if storing a range +// of R's type is not supported. void * vrange_storage::alloc_slot (const vrange &r) @@ -40,7 +41,6 @@ vrange_storage::alloc_slot (const vrange &r) if (is_a <irange> (r)) return irange_storage_slot::alloc_slot (*m_alloc, as_a <irange> (r)); - gcc_unreachable (); return NULL; } |