From dd393b871805ab4b0a76fb3d3755c757a98df30c Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Fri, 1 Mar 2019 14:04:23 -0500 Subject: [PATCH 029/169] 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 (1) for pointer deletion, following + pointer_hash ::mark_deleted. */ + struct var_state_t { //typedef var_state_t value_type; @@ -173,7 +178,7 @@ template <> inline void pod_hash_traits::mark_deleted (value_type &v) { - v = var_state_t (NULL_TREE, 0); + v = var_state_t (reinterpret_cast (1), 0); } template <> inline void @@ -185,7 +190,7 @@ template <> inline bool pod_hash_traits::is_deleted (value_type v) { - return (v.m_var == NULL_TREE && v.m_state == 0); + return (v.m_var == reinterpret_cast (1) && v.m_state == 0); } template <> inline bool @@ -220,8 +225,8 @@ template <> inline void pod_hash_traits::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 (1), 0)), + summary_point (0, var_state_t (reinterpret_cast (1), 0))); } template <> inline void @@ -234,7 +239,7 @@ template <> inline bool pod_hash_traits::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 (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::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 (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: " -#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