From: Jakub Jelinek <jakub@redhat.com>
To: David Malcolm <dmalcolm@redhat.com>
Cc: law@redhat.com, Richard Biener <rguenther@suse.de>,
gcc-patches@gcc.gnu.org
Subject: Re: Analyzer status
Date: Tue, 14 Jan 2020 01:29:00 -0000 [thread overview]
Message-ID: <20200113232635.GW10088@tucnak> (raw)
In-Reply-To: <20200113225614.GV10088@tucnak>
On Mon, Jan 13, 2020 at 11:56:14PM +0100, Jakub Jelinek wrote:
> > Some options:
> > (a) the patch to fix hash_table::empty, and the analyzer kit
> > (b) the analyzer kit with the following kludge
> > (c) someone with better C++-fu than me figure out a way to get the
> > memset optimization for hash_map with 0-valued empty (or to give me
> > some suggestions)
> > (d) not merge the analyzer for gcc 10
>
> For (c), I see right now we have 37 mark_empty definitions:
> find -type f | grep -v 'testsuite/\|ChangeLog' | xargs grep mark_empty | wc -l
> 37
> >From quick skimming of them, most of them are just zeroing one or more
> fields, exceptions are profile.c, attribs.c (this one only in self-tests
> and it is unclear why deleted is two NULLs and empty two ""s rather than
> vice versa), and gcov.c. Also, int_hash can be zero or non-zero, depending
> on template argument, e.g.
> typedef hash_map<int_hash <unsigned int, -1U>, unsigned int> live_vars_map;
> struct uid_hash : int_hash <int, -1, -2> {};
> are not either.
> Can't we add next to the mark_empty and is_empty methods also a static const
> bool data member empty_zero_p or similar and use it in in the two
> hash-table.h spots where this would make a difference?
> In alloc_entries the
> for (size_t i = 0; i < n; i++)
> mark_empty (nentries[i]);
> loop could be conditionalized on !Descriptor::empty_zero_p because both
> allocation paths actually allocate cleared memory, and in the spot
> you are talking about.
Just as a proof of concept, the following compiles (but haven't done any
testing beoyond that, not even looked if/when the memcpy vs. loop is in
there), the formatting/placement of the static data members could be
adjusted, in graphite.c I just gave up (it is weird, empty is when one field
is NULL, deleted when another field is NULL, but what is zeroed memory, is
that both empty and deleted at the same time?).
diff --git a/gcc/attribs.c b/gcc/attribs.c
index ca89443eb3e..c66d4ae2c06 100644
--- a/gcc/attribs.c
+++ b/gcc/attribs.c
@@ -2048,6 +2048,8 @@ struct excl_hash_traits: typed_noop_remove<excl_pair>
x = value_type (NULL, NULL);
}
+ static const bool empty_zero_p = false;
+
static void mark_empty (value_type &x)
{
x = value_type ("", "");
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 3d764bb6928..f3aeb7475da 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -3045,6 +3045,8 @@ struct source_location_table_entry_hash
ref.var = NULL_TREE;
}
+ static const bool empty_zero_p = true;
+
static void
mark_empty (source_location_table_entry &ref)
{
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 98572bdbad1..c3ca4c8dace 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -900,6 +900,7 @@ struct named_decl_hash : ggc_remove <tree>
inline static hashval_t hash (const value_type decl);
inline static bool equal (const value_type existing, compare_type candidate);
+ static const bool empty_zero_p = true;
static inline void mark_empty (value_type &p) {p = NULL_TREE;}
static inline bool is_empty (value_type p) {return !p;}
@@ -1870,6 +1871,7 @@ struct named_label_hash : ggc_remove <named_label_entry *>
inline static hashval_t hash (value_type);
inline static bool equal (const value_type, compare_type);
+ static const bool empty_zero_p = true;
inline static void mark_empty (value_type &p) {p = NULL;}
inline static bool is_empty (value_type p) {return !p;}
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index a641667991f..042d6fa12df 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -120,6 +120,7 @@ struct mangled_decl_hash : ggc_remove <tree>
return candidate == name;
}
+ static const bool empty_zero_p = true;
static inline void mark_empty (value_type &p) {p = NULL_TREE;}
static inline bool is_empty (value_type p) {return !p;}
diff --git a/gcc/gcov.c b/gcc/gcov.c
index 1dca3049777..a291bac3e9e 100644
--- a/gcc/gcov.c
+++ b/gcc/gcov.c
@@ -1225,6 +1225,8 @@ struct function_start_pair_hash : typed_noop_remove <function_start>
ref.start_line = ~1U;
}
+ static const bool empty_zero_p = false;
+
static void
mark_empty (function_start &ref)
{
diff --git a/gcc/graphite.c b/gcc/graphite.c
index 0ac46766b15..27f1e486e1f 100644
--- a/gcc/graphite.c
+++ b/gcc/graphite.c
@@ -233,6 +233,7 @@ struct sese_scev_hash : typed_noop_remove <seir_cache_key>
&& operand_equal_p (key1.expr, key2.expr, 0));
}
static void mark_deleted (seir_cache_key &key) { key.expr = NULL_TREE; }
+ static const bool empty_zero_p = false;
static void mark_empty (seir_cache_key &key) { key.entry_dest = 0; }
static bool is_deleted (const seir_cache_key &key) { return !key.expr; }
static bool is_empty (const seir_cache_key &key) { return key.entry_dest == 0; }
diff --git a/gcc/hash-map-traits.h b/gcc/hash-map-traits.h
index 4764380b364..3b16be35f7d 100644
--- a/gcc/hash-map-traits.h
+++ b/gcc/hash-map-traits.h
@@ -36,6 +36,7 @@ struct simple_hashmap_traits
static inline hashval_t hash (const key_type &);
static inline bool equal_keys (const key_type &, const key_type &);
template <typename T> static inline void remove (T &);
+ static const bool empty_zero_p = H::empty_zero_p;
template <typename T> static inline bool is_empty (const T &);
template <typename T> static inline bool is_deleted (const T &);
template <typename T> static inline void mark_empty (T &);
@@ -113,6 +114,7 @@ template <typename Value>
struct unbounded_hashmap_traits
{
template <typename T> static inline void remove (T &);
+ static const bool empty_zero_p = default_hash_traits <Value>::empty_zero_p;
template <typename T> static inline bool is_empty (const T &);
template <typename T> static inline bool is_deleted (const T &);
template <typename T> static inline void mark_empty (T &);
diff --git a/gcc/hash-map.h b/gcc/hash-map.h
index 7cb466767ea..5b8fd184e32 100644
--- a/gcc/hash-map.h
+++ b/gcc/hash-map.h
@@ -66,6 +66,7 @@ class GTY((user)) hash_map
return Traits::is_deleted (e);
}
+ static const bool empty_zero_p = Traits::empty_zero_p;
static void mark_empty (hash_entry &e) { Traits::mark_empty (e); }
static bool is_empty (const hash_entry &e) { return Traits::is_empty (e); }
diff --git a/gcc/hash-set-tests.c b/gcc/hash-set-tests.c
index 696e35e9be0..bb32094be20 100644
--- a/gcc/hash-set-tests.c
+++ b/gcc/hash-set-tests.c
@@ -199,6 +199,8 @@ struct value_hash_traits: int_hash<int, -1, -2>
base_type::mark_deleted (v.val);
}
+ static const bool empty_zero_p = false;
+
static void mark_empty (value_type &v)
{
base_type::mark_empty (v.val);
diff --git a/gcc/hash-table.h b/gcc/hash-table.h
index e0ddac5f578..a1423c78112 100644
--- a/gcc/hash-table.h
+++ b/gcc/hash-table.h
@@ -713,8 +713,9 @@ hash_table<Descriptor, Lazy,
nentries = ::ggc_cleared_vec_alloc<value_type> (n PASS_MEM_STAT);
gcc_assert (nentries != NULL);
- for (size_t i = 0; i < n; i++)
- mark_empty (nentries[i]);
+ if (!Descriptor::empty_zero_p)
+ for (size_t i = 0; i < n; i++)
+ mark_empty (nentries[i]);
return nentries;
}
@@ -867,8 +868,11 @@ hash_table<Descriptor, Lazy, Allocator>::empty_slow ()
m_size = nsize;
m_size_prime_index = nindex;
}
- else
+ else if (Descriptor::empty_zero_p)
memset ((void *) entries, 0, size * sizeof (value_type));
+ else
+ for (size_t i = 0; i < size; i++)
+ mark_empty (entries[i]);
m_n_deleted = 0;
m_n_elements = 0;
diff --git a/gcc/hash-traits.h b/gcc/hash-traits.h
index d259a41a418..3bca74c56ea 100644
--- a/gcc/hash-traits.h
+++ b/gcc/hash-traits.h
@@ -88,6 +88,7 @@ struct int_hash : typed_noop_remove <Type>
static inline hashval_t hash (value_type);
static inline bool equal (value_type existing, value_type candidate);
static inline void mark_deleted (Type &);
+ static const bool empty_zero_p = Empty == 0;
static inline void mark_empty (Type &);
static inline bool is_deleted (Type);
static inline bool is_empty (Type);
@@ -150,6 +151,7 @@ struct pointer_hash
static inline bool equal (const value_type &existing,
const compare_type &candidate);
static inline void mark_deleted (Type *&);
+ static const bool empty_zero_p = true;
static inline void mark_empty (Type *&);
static inline bool is_deleted (Type *);
static inline bool is_empty (Type *);
@@ -323,6 +325,7 @@ struct pair_hash
static inline bool equal (const value_type &, const compare_type &);
static inline void remove (value_type &);
static inline void mark_deleted (value_type &);
+ static const bool empty_zero_p = T1::empty_zero_p;
static inline void mark_empty (value_type &);
static inline bool is_deleted (const value_type &);
static inline bool is_empty (const value_type &);
diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
index b888186134c..f0031957375 100644
--- a/gcc/ipa-devirt.c
+++ b/gcc/ipa-devirt.c
@@ -150,6 +150,7 @@ struct default_hash_traits <type_pair>
{
return TYPE_UID (p.first) ^ TYPE_UID (p.second);
}
+ static const bool empty_zero_p = true;
static bool
is_empty (type_pair p)
{
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index 6dc3cf6b355..12cdb95cf2a 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -78,6 +78,7 @@ struct ipa_bit_ggc_hash_traits : public ggc_cache_remove <ipa_bits *>
{
return a->value == b->value && a->mask == b->mask;
}
+ static const bool empty_zero_p = true;
static void
mark_empty (ipa_bits *&p)
{
@@ -123,6 +124,7 @@ struct ipa_vr_ggc_hash_traits : public ggc_cache_remove <value_range *>
{
return a->equal_p (*b);
}
+ static const bool empty_zero_p = true;
static void
mark_empty (value_range *&p)
{
diff --git a/gcc/profile.c b/gcc/profile.c
index e124dc6173a..6a2de21c3bd 100644
--- a/gcc/profile.c
+++ b/gcc/profile.c
@@ -932,6 +932,8 @@ struct location_triplet_hash : typed_noop_remove <location_triplet>
ref.lineno = -1;
}
+ static const bool empty_zero_p = false;
+
static void
mark_empty (location_triplet &ref)
{
diff --git a/gcc/sanopt.c b/gcc/sanopt.c
index 8a29abe99e2..619aae45a15 100644
--- a/gcc/sanopt.c
+++ b/gcc/sanopt.c
@@ -129,6 +129,8 @@ struct sanopt_tree_triplet_hash : typed_noop_remove <sanopt_tree_triplet>
ref.t1 = reinterpret_cast<tree> (1);
}
+ static const bool empty_zero_p = true;
+
static void
mark_empty (sanopt_tree_triplet &ref)
{
@@ -184,6 +186,8 @@ struct sanopt_tree_couple_hash : typed_noop_remove <sanopt_tree_couple>
ref.ptr = reinterpret_cast<tree> (1);
}
+ static const bool empty_zero_p = true;
+
static void
mark_empty (sanopt_tree_couple &ref)
{
diff --git a/gcc/tree-hasher.h b/gcc/tree-hasher.h
index 787d1ad6a62..9194d6227a2 100644
--- a/gcc/tree-hasher.h
+++ b/gcc/tree-hasher.h
@@ -40,6 +40,7 @@ struct int_tree_hasher
}
static void mark_deleted (value_type &v) { v.to = reinterpret_cast<tree> (0x1); }
static bool is_empty (const value_type &v) { return v.to == NULL; }
+ static const bool empty_zero_p = true;
static void mark_empty (value_type &v) { v.to = NULL; }
static void remove (value_type &) {}
};
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 6f6b19eb165..3b27c50ef75 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -335,6 +335,7 @@ struct vn_ssa_aux_hasher : typed_noop_remove <vn_ssa_aux_t>
static inline hashval_t hash (const value_type &);
static inline bool equal (const value_type &, const compare_type &);
static inline void mark_deleted (value_type &) {}
+ static const bool empty_zero_p = true;
static inline void mark_empty (value_type &e) { e = NULL; }
static inline bool is_deleted (value_type &) { return false; }
static inline bool is_empty (value_type &e) { return e == NULL; }
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 9cb724b95ae..d164937b4b0 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -1193,6 +1193,7 @@ struct bst_traits
static inline bool equal (value_type existing, value_type candidate);
static inline bool is_empty (value_type x) { return !x.exists (); }
static inline bool is_deleted (value_type x) { return !x.exists (); }
+ static const bool empty_zero_p = true;
static inline void mark_empty (value_type &x) { x.release (); }
static inline void mark_deleted (value_type &x) { x.release (); }
static inline void remove (value_type &x) { x.release (); }
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 375fba28d20..ed7fcb0b825 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -232,6 +232,8 @@ struct default_hash_traits<scalar_cond_masked_key>
&& operand_equal_p (existing.op1, candidate.op1, 0));
}
+ static const bool empty_zero_p = true;
+
static inline void
mark_empty (value_type &v)
{
Jakub
next prev parent reply other threads:[~2020-01-13 23:26 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-01-13 23:42 David Malcolm
2020-01-13 23:55 ` Jakub Jelinek
2020-01-14 1:29 ` Jakub Jelinek [this message]
2020-01-14 1:30 ` David Malcolm
2020-01-14 2:58 ` Jakub Jelinek
2020-01-14 4:52 ` David Malcolm
2020-01-14 8:24 ` [PATCH 1/2] hash-table.h: support non-zero empty values in empty_slow (v2) David Malcolm
2020-01-14 7:55 ` [PATCH 2/2] analyzer: add empty_zero_p for the various hash traits David Malcolm
2020-01-14 11:07 ` [PATCH 1/2] hash-table.h: support non-zero empty values in empty_slow (v2) Jakub Jelinek
2020-01-14 19:14 ` David Malcolm
2020-01-14 8:31 ` Analyzer status Richard Biener
2020-01-14 21:10 ` Analyzer committed to master (was Re: Analyzer status) David Malcolm
2020-01-15 12:37 ` Rainer Orth
2020-01-15 20:12 ` Dimitar Dimitrov
2020-01-15 20:29 ` Iain Sandoe
2020-01-15 20:53 ` David Malcolm
2020-01-16 6:43 ` [PATCH] analyzer: fix handling of negative byte offsets (PR 93281) David Malcolm
2020-01-16 7:39 ` Richard Biener
2020-01-16 8:56 ` Jakub Jelinek
2020-01-18 17:02 ` Analyzer committed to master (was Re: Analyzer status) Rainer Orth
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200113232635.GW10088@tucnak \
--to=jakub@redhat.com \
--cc=dmalcolm@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=law@redhat.com \
--cc=rguenther@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).