3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-06-19 07:06:28 +00:00

goal2sat: skip caching singly-referenced AST nodes

A node that is referenced only once in the goal can never produce a
cache hit: it appears at most once during goal2sat conversion, so its
cached entry would never be retrieved. Memoizing it is pure overhead.

Guard the cache on the single-reference condition in cache(),
get_cached(), and process_cached(). The guard is applied symmetrically
to both m_app2lit and m_lit2app so the two maps stay in sync and
pop()/uncache() continue to clean up consistently.

Also pre-allocate the mk_eq output vector in bit_blaster_tpl with
reserve(sz) to avoid incremental reallocations during per-bit expansion.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Yusen Su 2024-09-23 00:12:46 -04:00
parent f508854fe5
commit 969828b701
2 changed files with 13 additions and 4 deletions

View file

@ -768,6 +768,8 @@ void bit_blaster_tpl<Cfg>::mk_smod(unsigned sz, expr * const * a_bits, expr * co
template<typename Cfg>
void bit_blaster_tpl<Cfg>::mk_eq(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref & out) {
expr_ref_vector out_bits(m());
out_bits.reserve(sz);
out_bits.reset();
for (unsigned i = 0; i < sz; ++i) {
mk_iff(a_bits[i], b_bits[i], out);
out_bits.push_back(out);

View file

@ -261,16 +261,23 @@ struct goal2sat::imp : public sat::sat_internalizer {
void cache(app* t, sat::literal l) override {
force_push();
m_cache_trail.push_back(t);
// Only memoize nodes that can be revisited: a singly-referenced
// node appears once in the goal, so it never produces a cache hit.
// Skipping it keeps m_app2lit and m_lit2app in sync (both empty for
// such nodes) so pop()/uncache() clean up consistently.
if (t->get_ref_count() <= 1)
return;
SASSERT(!m_app2lit.contains(t));
SASSERT(!m_lit2app.contains(l.index()));
m_app2lit.insert(t, l);
m_lit2app.insert(l.index(), t);
m_cache_trail.push_back(t);
}
sat::literal get_cached(app* t) const override {
sat::literal lit = sat::null_literal;
m_app2lit.find(t, lit);
if (t->get_ref_count() > 1)
m_app2lit.find(t, lit);
return lit;
}
@ -279,7 +286,7 @@ struct goal2sat::imp : public sat::sat_internalizer {
SASSERT(lit == sat::null_literal || l == lit);
return l == lit;
}
void convert_atom(expr * t, bool root, bool sign) {
SASSERT(m.is_bool(t));
sat::literal l;
@ -346,7 +353,7 @@ struct goal2sat::imp : public sat::sat_internalizer {
bool process_cached(app* t, bool root, bool sign) {
sat::literal l = sat::null_literal;
if (!m_app2lit.find(t, l))
if (t->get_ref_count() <= 1 || !m_app2lit.find(t, l))
return false;
if (sign)
l.neg();