]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/tree.c
Multi-range implementation for value_range (irange).
[thirdparty/gcc.git] / gcc / tree.c
index 6522a089ddfe742e120e91666e651111a572ebb0..01a342c5b9235e1e21a63bf47879de65659e6bc2 100644 (file)
@@ -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
        {