diff options
Diffstat (limited to 'gcc/tree.c')
-rw-r--r-- | gcc/tree.c | 85 |
1 files changed, 57 insertions, 28 deletions
@@ -1483,6 +1483,31 @@ int_cst_hasher::equal (tree x, tree y) return true; } +/* Cache wide_int CST into the TYPE_CACHED_VALUES cache for TYPE. + SLOT is the slot entry to store it in, and MAX_SLOTS is the maximum + number of slots that can be cached for the type. */ + +static inline tree +cache_wide_int_in_type_cache (tree type, const wide_int &cst, + int slot, int max_slots) +{ + gcc_checking_assert (slot >= 0); + /* Initialize cache. */ + if (!TYPE_CACHED_VALUES_P (type)) + { + TYPE_CACHED_VALUES_P (type) = 1; + TYPE_CACHED_VALUES (type) = make_tree_vec (max_slots); + } + tree t = TREE_VEC_ELT (TYPE_CACHED_VALUES (type), slot); + if (!t) + { + /* Create a new shared int. */ + t = build_new_int_cst (type, cst); + TREE_VEC_ELT (TYPE_CACHED_VALUES (type), slot) = t; + } + return t; +} + /* Create an INT_CST node of TYPE and value CST. The returned node is always shared. For small integers we use a per-type vector cache, for larger ones we use a single hash table. @@ -1515,6 +1540,28 @@ wide_int_to_tree_1 (tree type, const wide_int_ref &pcst) wide_int cst = wide_int::from (pcst, prec, sgn); unsigned int ext_len = get_int_cst_ext_nunits (type, cst); + enum tree_code code = TREE_CODE (type); + if (code == POINTER_TYPE || code == REFERENCE_TYPE) + { + /* Cache NULL pointer and zero bounds. */ + if (cst == 0) + ix = 0; + /* Cache upper bounds of pointers. */ + else if (cst == wi::max_value (prec, sgn)) + ix = 1; + /* Cache 1 which is used for a non-zero range. */ + else if (cst == 1) + ix = 2; + + if (ix >= 0) + { + t = cache_wide_int_in_type_cache (type, cst, ix, 3); + /* Make sure no one is clobbering the shared constant. */ + gcc_checking_assert (TREE_TYPE (t) == type + && cst == wi::to_wide (t)); + return t; + } + } if (ext_len == 1) { /* We just need to store a single HOST_WIDE_INT. */ @@ -1524,7 +1571,7 @@ wide_int_to_tree_1 (tree type, const wide_int_ref &pcst) else hwi = cst.to_shwi (); - switch (TREE_CODE (type)) + switch (code) { case NULLPTR_TYPE: gcc_assert (hwi == 0); @@ -1532,12 +1579,7 @@ wide_int_to_tree_1 (tree type, const wide_int_ref &pcst) case POINTER_TYPE: case REFERENCE_TYPE: - /* Cache NULL pointer and zero bounds. */ - if (hwi == 0) - { - limit = 1; - ix = 0; - } + /* Ignore pointers, as they were already handled above. */ break; case BOOLEAN_TYPE: @@ -1574,27 +1616,14 @@ wide_int_to_tree_1 (tree type, const wide_int_ref &pcst) if (ix >= 0) { - /* Look for it in the type's vector of small shared ints. */ - if (!TYPE_CACHED_VALUES_P (type)) - { - TYPE_CACHED_VALUES_P (type) = 1; - TYPE_CACHED_VALUES (type) = make_tree_vec (limit); - } - - t = TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix); - if (t) - /* Make sure no one is clobbering the shared constant. */ - gcc_checking_assert (TREE_TYPE (t) == type - && TREE_INT_CST_NUNITS (t) == 1 - && TREE_INT_CST_OFFSET_NUNITS (t) == 1 - && TREE_INT_CST_EXT_NUNITS (t) == 1 - && TREE_INT_CST_ELT (t, 0) == hwi); - else - { - /* Create a new shared int. */ - t = build_new_int_cst (type, cst); - TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t; - } + t = cache_wide_int_in_type_cache (type, cst, ix, limit); + /* Make sure no one is clobbering the shared constant. */ + gcc_checking_assert (TREE_TYPE (t) == type + && TREE_INT_CST_NUNITS (t) == 1 + && TREE_INT_CST_OFFSET_NUNITS (t) == 1 + && TREE_INT_CST_EXT_NUNITS (t) == 1 + && TREE_INT_CST_ELT (t, 0) == hwi); + return t; } else { |