public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r14-1664] analyzer: add caching to globals with initializers [PR110112]
@ 2023-06-09 22:05 David Malcolm
  0 siblings, 0 replies; only message in thread
From: David Malcolm @ 2023-06-09 22:05 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:fe9771b59f576fb37e762013ef5d9b26162e3a88

commit r14-1664-gfe9771b59f576fb37e762013ef5d9b26162e3a88
Author: David Malcolm <dmalcolm@redhat.com>
Date:   Fri Jun 9 17:58:33 2023 -0400

    analyzer: add caching to globals with initializers [PR110112]
    
    PR analyzer/110112 notes that -fanalyzer is extremely slow on a source
    file with large read-only static arrays, repeatedly building the
    same compound_svalue representing the full initializer, and repeatedly
    building svalues representing parts of the the full initialiazer.
    
    This patch adds caches for both of these; together they reduce the time
    taken by -fanalyzer -O2 on the testcase in the bug for an optimized
    build:
      91.2s : no caches (status quo)
      32.4s : cache in decl_region::get_svalue_for_constructor
       3.7s : cache in region::get_initial_value_at_main
       3.1s : both caches (this patch)
    
    gcc/analyzer/ChangeLog:
            PR analyzer/110112
            * region-model.cc (region_model::get_initial_value_for_global):
            Move code to region::calc_initial_value_at_main.
            * region.cc (region::get_initial_value_at_main): New function.
            (region::calc_initial_value_at_main): New function, based on code
            in region_model::get_initial_value_for_global.
            (region::region): Initialize m_cached_init_sval_at_main.
            (decl_region::get_svalue_for_constructor): Add a cache, splitting
            out body to...
            (decl_region::calc_svalue_for_constructor): ...this new function.
            * region.h (region::get_initial_value_at_main): New decl.
            (region::calc_initial_value_at_main): New decl.
            (region::m_cached_init_sval_at_main): New field.
            (decl_region::decl_region): Initialize m_ctor_svalue.
            (decl_region::calc_svalue_for_constructor): New decl.
            (decl_region::m_ctor_svalue): New field.
    
    Signed-off-by: David Malcolm <dmalcolm@redhat.com>

Diff:
---
 gcc/analyzer/region-model.cc | 25 +---------------
 gcc/analyzer/region.cc       | 71 ++++++++++++++++++++++++++++++++++++++++----
 gcc/analyzer/region.h        | 14 ++++++++-
 3 files changed, 79 insertions(+), 31 deletions(-)

diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index fb96cd54940..b11cc6c5bb4 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -2355,30 +2355,7 @@ region_model::get_initial_value_for_global (const region *reg) const
      the initial value of REG can be taken from the initialization value
      of the decl.  */
   if (called_from_main_p () || TREE_READONLY (decl))
-    {
-      /* Attempt to get the initializer value for base_reg.  */
-      if (const svalue *base_reg_init
-	    = base_reg->get_svalue_for_initializer (m_mgr))
-	{
-	  if (reg == base_reg)
-	    return base_reg_init;
-	  else
-	    {
-	      /* Get the value for REG within base_reg_init.  */
-	      binding_cluster c (base_reg);
-	      c.bind (m_mgr->get_store_manager (), base_reg, base_reg_init);
-	      const svalue *sval
-		= c.get_any_binding (m_mgr->get_store_manager (), reg);
-	      if (sval)
-		{
-		  if (reg->get_type ())
-		    sval = m_mgr->get_or_create_cast (reg->get_type (),
-						      sval);
-		  return sval;
-		}
-	    }
-	}
-    }
+    return reg->get_initial_value_at_main (m_mgr);
 
   /* Otherwise, return INIT_VAL(REG).  */
   return m_mgr->get_or_create_initial_value (reg);
diff --git a/gcc/analyzer/region.cc b/gcc/analyzer/region.cc
index 8f0eb569b33..098b43608ef 100644
--- a/gcc/analyzer/region.cc
+++ b/gcc/analyzer/region.cc
@@ -272,6 +272,51 @@ region::can_have_initial_svalue_p () const
     }
 }
 
+/* For regions within a global decl, get the svalue for the initial
+   value of this region when the program starts, caching the result.  */
+
+const svalue *
+region::get_initial_value_at_main (region_model_manager *mgr) const
+{
+  if (!m_cached_init_sval_at_main)
+    m_cached_init_sval_at_main = calc_initial_value_at_main (mgr);
+  return m_cached_init_sval_at_main;
+}
+
+/* Implementation of region::get_initial_value_at_main.  */
+
+const svalue *
+region::calc_initial_value_at_main (region_model_manager *mgr) const
+{
+  const decl_region *base_reg = get_base_region ()->dyn_cast_decl_region ();
+  gcc_assert (base_reg);
+
+  /* Attempt to get the initializer value for base_reg.  */
+  if (const svalue *base_reg_init
+      = base_reg->get_svalue_for_initializer (mgr))
+    {
+      if (this == base_reg)
+	return base_reg_init;
+      else
+	{
+	  /* Get the value for REG within base_reg_init.  */
+	  binding_cluster c (base_reg);
+	  c.bind (mgr->get_store_manager (), base_reg, base_reg_init);
+	  const svalue *sval
+	    = c.get_any_binding (mgr->get_store_manager (), this);
+	  if (sval)
+	    {
+	      if (get_type ())
+		sval = mgr->get_or_create_cast (get_type (), sval);
+	      return sval;
+	    }
+	}
+    }
+
+  /* Otherwise, return INIT_VAL(REG).  */
+  return mgr->get_or_create_initial_value (this);
+}
+
 /* If this region is a decl_region, return the decl.
    Otherwise return NULL.  */
 
@@ -701,7 +746,7 @@ region::is_named_decl_p (const char *decl_name) const
 
 region::region (complexity c, unsigned id, const region *parent, tree type)
 : m_complexity (c), m_id (id), m_parent (parent), m_type (type),
-  m_cached_offset (NULL)
+  m_cached_offset (NULL), m_cached_init_sval_at_main (NULL)
 {
   gcc_assert (type == NULL_TREE || TYPE_P (type));
 }
@@ -1170,14 +1215,13 @@ decl_region::maybe_get_constant_value (region_model_manager *mgr) const
   return NULL;
 }
 
-/* Get an svalue for CTOR, a CONSTRUCTOR for this region's decl.  */
+/* Implementation of decl_region::get_svalue_for_constructor
+   for when the cached value hasn't yet been calculated.  */
 
 const svalue *
-decl_region::get_svalue_for_constructor (tree ctor,
-					 region_model_manager *mgr) const
+decl_region::calc_svalue_for_constructor (tree ctor,
+					  region_model_manager *mgr) const
 {
-  gcc_assert (!TREE_CLOBBER_P (ctor));
-
   /* Create a binding map, applying ctor to it, using this
      decl_region as the base region when building child regions
      for offset calculations.  */
@@ -1189,6 +1233,21 @@ decl_region::get_svalue_for_constructor (tree ctor,
   return mgr->get_or_create_compound_svalue (get_type (), map);
 }
 
+/* Get an svalue for CTOR, a CONSTRUCTOR for this region's decl.  */
+
+const svalue *
+decl_region::get_svalue_for_constructor (tree ctor,
+					 region_model_manager *mgr) const
+{
+  gcc_assert (!TREE_CLOBBER_P (ctor));
+  gcc_assert (ctor == DECL_INITIAL (m_decl));
+
+  if (!m_ctor_svalue)
+    m_ctor_svalue = calc_svalue_for_constructor (ctor, mgr);
+
+  return m_ctor_svalue;
+}
+
 /* For use on decl_regions for global variables.
 
    Get an svalue for the initial value of this region at entry to
diff --git a/gcc/analyzer/region.h b/gcc/analyzer/region.h
index 5df0ae7487b..270e5042eeb 100644
--- a/gcc/analyzer/region.h
+++ b/gcc/analyzer/region.h
@@ -161,6 +161,7 @@ public:
   const frame_region *maybe_get_frame_region () const;
   enum memory_space get_memory_space () const;
   bool can_have_initial_svalue_p () const;
+  const svalue *get_initial_value_at_main (region_model_manager *mgr) const;
 
   tree maybe_get_decl () const;
 
@@ -240,6 +241,7 @@ public:
 
  private:
   region_offset calc_offset (region_model_manager *mgr) const;
+  const svalue *calc_initial_value_at_main (region_model_manager *mgr) const;
 
   complexity m_complexity;
   unsigned m_id; // purely for deterministic sorting at this stage, for dumps
@@ -247,6 +249,10 @@ public:
   tree m_type;
 
   mutable region_offset *m_cached_offset;
+
+  /* For regions within a global decl, a cache of the svalue for the initial
+     value of this region when the program starts.  */
+  mutable const svalue *m_cached_init_sval_at_main;
 };
 
 } // namespace ana
@@ -696,7 +702,8 @@ class decl_region : public region
 public:
   decl_region (unsigned id, const region *parent, tree decl)
   : region (complexity (parent), id, parent, TREE_TYPE (decl)), m_decl (decl),
-    m_tracked (calc_tracked_p (decl))
+    m_tracked (calc_tracked_p (decl)),
+    m_ctor_svalue (NULL)
   {}
 
   enum region_kind get_kind () const final override { return RK_DECL; }
@@ -716,6 +723,8 @@ public:
   const svalue *get_svalue_for_initializer (region_model_manager *mgr) const;
 
 private:
+  const svalue *calc_svalue_for_constructor (tree ctor,
+					     region_model_manager *mgr) const;
   static bool calc_tracked_p (tree decl);
 
   tree m_decl;
@@ -725,6 +734,9 @@ private:
      store objects).
      This can be debugged using -fdump-analyzer-untracked.  */
   bool m_tracked;
+
+  /* Cached result of get_svalue_for_constructor.  */
+  mutable const svalue *m_ctor_svalue;
 };
 
 } // namespace ana

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-06-09 22:05 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-09 22:05 [gcc r14-1664] analyzer: add caching to globals with initializers [PR110112] David Malcolm

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).