From dd393b871805ab4b0a76fb3d3755c757a98df30c Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Fri, 1 Mar 2019 14:04:23 -0500
Subject: [PATCH 029/161] FIXME: fix hash_traits to distinguish deleted from
 empty

---
 gcc/analyzer/engine.cc                            | 54 ++++++++++++++++++-----
 gcc/testsuite/gcc.dg/analyzer/malloc-1.c          |  5 +--
 gcc/testsuite/gcc.dg/analyzer/malloc-many-paths.c |  2 +-
 3 files changed, 44 insertions(+), 17 deletions(-)

diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index 6076537..1976a92 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -52,6 +52,11 @@ class sm_instance;
 
 ////////////////////////////////////////////////////////////////////////////
 
+/* Gotcha: it's required that hashables have a different "deleted" value
+   from the "empty" value.
+   We use reinterpret_cast<Type *> (1) for pointer deletion, following
+   pointer_hash <Type>::mark_deleted.  */
+
 struct var_state_t
 {
   //typedef var_state_t value_type;
@@ -173,7 +178,7 @@ template <>
 inline void
 pod_hash_traits<var_state_t>::mark_deleted (value_type &v)
 {
-  v = var_state_t (NULL_TREE, 0);
+  v = var_state_t (reinterpret_cast<tree> (1), 0);
 }
 template <>
 inline void
@@ -185,7 +190,7 @@ template <>
 inline bool
 pod_hash_traits<var_state_t>::is_deleted (value_type v)
 {
-  return (v.m_var == NULL_TREE && v.m_state == 0);
+  return (v.m_var == reinterpret_cast<tree> (1) && v.m_state == 0);
 }
 template <>
 inline bool
@@ -220,8 +225,8 @@ template <>
 inline void
 pod_hash_traits<summary_edge>::mark_deleted (value_type &v)
 {
-  v = summary_edge (summary_point (0, var_state_t (NULL_TREE, 0)),
-		    summary_point (0, var_state_t (NULL_TREE, 0)));
+  v = summary_edge (summary_point (0, var_state_t (reinterpret_cast<tree> (1), 0)),
+		    summary_point (0, var_state_t (reinterpret_cast<tree> (1), 0)));
 }
 template <>
 inline void
@@ -234,7 +239,7 @@ template <>
 inline bool
 pod_hash_traits<summary_edge>::is_deleted (value_type v)
 {
-  return v.m_start.m_varstate.m_var == NULL_TREE;
+  return v.m_start.m_varstate.m_var == reinterpret_cast<tree> (1);
 }
 template <>
 inline bool
@@ -517,18 +522,29 @@ void
 engine::prune_active_vars_to_cache_misses (sm_instance *sm_inst,
 					   const supernode *node)
 {
+  JIT_LOG_FUNC_1 (get_logger (), "SN: %i", node->m_index);
+  if (get_logger ())
+    {
+      log ("sm_inst: %s", sm_inst->to_str (m_sm).c_str ());
+      log ("blk_add: %s",
+	   get_data_for_node (node).m_blk_add.to_str (m_sm).c_str ());
+      log ("blk_transition: %s",
+	   get_data_for_node (node).m_blk_transition.to_str (m_sm).c_str ());
+    }
+
   const set_of_summary_edges &edges = get_data_for_node (node).m_blk_transition;
   for (set_of_summary_edges::iterator iter = edges.begin ();
        iter != edges.end ();
        ++iter)
     {
+      var_state_t cached_start_vs = (*iter).m_start.m_varstate;
       // FIXME: I think we need a match on gstate, too
-      if (sm_inst->m_active_vars.m_set.contains ((*iter).m_start.m_varstate))
+      if (sm_inst->m_active_vars.m_set.contains (cached_start_vs))
 	{
 	  if (get_logger ())
 	    log ("cache hit: %s",
 		 (*iter).m_start.m_varstate.to_str (m_sm).c_str ());
-	  sm_inst->m_active_vars.m_set.remove ((*iter).m_start.m_varstate);
+	  sm_inst->m_active_vars.m_set.remove (cached_start_vs);
 	  m_num_cache_hits++;
 	}
     }
@@ -656,6 +672,17 @@ engine::add_blk_edges_to_cache (const supernode *node,
 				const sm_instance &sm_inst,
 				const sm_instance &old_sm_inst)
 {
+  JIT_LOG_FUNC_1 (get_logger (), "SN: %i", node->m_index);
+  if (get_logger ())
+    {
+      log ("sm_inst: %s", sm_inst.to_str (m_sm).c_str ());
+      log ("old_sm_inst: %s", old_sm_inst.to_str (m_sm).c_str ());
+      log ("blk_add was: %s",
+	   get_data_for_node (node).m_blk_add.to_str (m_sm).c_str ());
+      log ("blk_transition was: %s",
+	   get_data_for_node (node).m_blk_transition.to_str (m_sm).c_str ());
+    }
+
   /* Compute add and transition edges.  */
   log ("new block summary edges for SN %i", node->m_index);
   for (hash_set<var_state_t>::iterator iter = sm_inst.m_active_vars.m_set.begin ();
@@ -684,6 +711,14 @@ engine::add_blk_edges_to_cache (const supernode *node,
 			   e));
 	}
     }
+
+  if (get_logger ())
+    {
+      log ("blk_add now: %s",
+	   get_data_for_node (node).m_blk_add.to_str (m_sm).c_str ());
+      log ("blk_transition now: %s",
+	   get_data_for_node (node).m_blk_transition.to_str (m_sm).c_str ());
+    }
 }
 
 /* FIXME.  */
@@ -855,12 +890,7 @@ engine::on_phi (const supernode *node, const gphi *phi,
   size_t index = last_cfg_superedge->m_cfg_edge->dest_idx;
   tree src = gimple_phi_arg_def (const_cast <gphi *> (phi), index); // FIXME const_cast
   tree lhs = gimple_phi_result (phi);
-  // FIXME: this leads to infinite traversals on loops:
-  // e.g. for malloc-1.c, where we constantly hit:
-  //  "after pruning to cache, sm_inst: <start, {‘i_1’ null}>"
-#if 0
   on_assignment (node, phi, sm_inst, old_sm_inst, lhs, src, ps);
-#endif
 }
 
 void
diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-1.c b/gcc/testsuite/gcc.dg/analyzer/malloc-1.c
index 0ccbe09..3527eef 100644
--- a/gcc/testsuite/gcc.dg/analyzer/malloc-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/malloc-1.c
@@ -77,10 +77,7 @@ void test_9 (void)
   int i;
   for (i = 0; i < 1024; i++)
     free (ptr); /* { dg-error "double-free of 'ptr'" } */
-} /* { dg-error "leak of 'ptr'" } */ 
-/* FIXME: false positive about leak here: presumably we don't yet know
-   that the loop will execute at least once (presumably as our constraints
-   aren't clever enough).  */
+}
 
 void test_10 (void)
 {
diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-many-paths.c b/gcc/testsuite/gcc.dg/analyzer/malloc-many-paths.c
index 6e236dc..3bb3bd6 100644
--- a/gcc/testsuite/gcc.dg/analyzer/malloc-many-paths.c
+++ b/gcc/testsuite/gcc.dg/analyzer/malloc-many-paths.c
@@ -5,7 +5,7 @@ extern int foo (void);
 /* Ensure that we don't need to laboriously walk every path to get
    to the end of the function.  */
 
-#if 0
+#if 1
 int test_1 (int n)
 {
   int i, j, k;
-- 
1.8.5.3

