mirror of
https://github.com/Z3Prover/z3
synced 2025-04-29 11:55:51 +00:00
lazy multiplier experiment
this update provides a use case for and allows testing incremental multiplier compilation.
This commit is contained in:
parent
616fc2cbd5
commit
8dc8de8ccd
2 changed files with 63 additions and 0 deletions
|
@ -72,6 +72,55 @@ namespace bv {
|
|||
return expr_ref(bv.mk_numeral(val, get_bv_size(v)), m);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief expose the multiplication circuit lazily.
|
||||
It adds clauses for multiplier output one by one to enforce
|
||||
the semantics of multiplier semantics.
|
||||
*/
|
||||
|
||||
bool solver::check_lazy_mul(app* e, expr* arg_value, expr* mul_value) {
|
||||
SASSERT(e->get_num_args() >= 2);
|
||||
expr_ref_vector args(m), new_args(m), new_out(m);
|
||||
lazy_mul* lz = nullptr;
|
||||
rational v0, v1;
|
||||
unsigned sz, diff = 0;
|
||||
VERIFY(bv.is_numeral(arg_value, v0, sz));
|
||||
VERIFY(bv.is_numeral(mul_value, v1));
|
||||
for (diff = 0; diff < sz; ++diff)
|
||||
if (v0.get_bit(diff) != v1.get_bit(diff))
|
||||
break;
|
||||
SASSERT(diff < sz);
|
||||
auto set_bits = [&](unsigned j, expr_ref_vector& bits) {
|
||||
bits.reset();
|
||||
for (unsigned i = 0; i < sz; ++i)
|
||||
bits.push_back(bv.mk_bit2bool(e->get_arg(0), j));
|
||||
};
|
||||
if (!m_lazymul.find(e, lz)) {
|
||||
set_bits(0, args);
|
||||
for (unsigned j = 1; j < e->get_num_args(); ++j) {
|
||||
new_out.reset();
|
||||
set_bits(j, new_args);
|
||||
m_bb.mk_multiplier(sz, args.data(), new_args.data(), new_out);
|
||||
new_out.swap(args);
|
||||
}
|
||||
lz = alloc(lazy_mul, e, args);
|
||||
m_lazymul.insert(e, lz);
|
||||
ctx.push(new_obj_trail(lz));
|
||||
ctx.push(insert_obj_map(m_lazymul, e));
|
||||
}
|
||||
if (lz->m_out.size() == lz->m_bits)
|
||||
return false;
|
||||
for (unsigned i = lz->m_bits; i <= diff; ++i) {
|
||||
sat::literal bit1 = mk_literal(lz->m_out.get(i));
|
||||
sat::literal bit2 = mk_literal(bv.mk_bit2bool(e, i));
|
||||
add_equiv(bit1, bit2);
|
||||
}
|
||||
ctx.push(value_trail(lz->m_bits));
|
||||
IF_VERBOSE(1, verbose_stream() << "expand lazy mul " << mk_pp(e, m) << " to " << diff << "\n");
|
||||
lz->m_bits = diff;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool solver::check_mul(app* e) {
|
||||
SASSERT(e->get_num_args() >= 2);
|
||||
expr_ref_vector args(m);
|
||||
|
@ -96,6 +145,9 @@ namespace bv {
|
|||
if (!check_mul_invertibility(e, args, r1))
|
||||
return false;
|
||||
|
||||
if (!check_lazy_mul(e, r1, r2))
|
||||
return false;
|
||||
|
||||
// Some other possible approaches:
|
||||
// algebraic rules:
|
||||
// x*(y+z), and there are nodes for x*y or x*z -> x*(y+z) = x*y + x*z
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue