3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-13 12:28:44 +00:00

use native sdiv

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2025-01-03 10:56:15 -08:00
parent bfcd75595e
commit 5a57636cd8
5 changed files with 69 additions and 7 deletions

View file

@ -724,11 +724,11 @@ namespace sls {
case OP_BSMOD:
case OP_BSMOD_I:
case OP_BSMOD0:
return true;
default:
case OP_BSDIV:
case OP_BSDIV_I:
case OP_BSDIV0:
return true;
default:
return false;
}
}
@ -916,15 +916,17 @@ namespace sls {
case OP_BSMUL_OVFL:
verbose_stream() << mk_pp(e, m) << "\n";
return false;
case OP_BSDIV:
case OP_BSDIV_I:
case OP_BSDIV0:
return try_repair_sdiv(assign_value(e), wval(e, 0), wval(e, 1), i);
case OP_BSREM:
case OP_BSREM_I:
case OP_BSREM0:
case OP_BSMOD:
case OP_BSMOD_I:
case OP_BSMOD0:
case OP_BSDIV:
case OP_BSDIV_I:
case OP_BSDIV0:
UNREACHABLE();
// these are currently compiled to udiv and urem.
// there is an equation that enforces equality between the semantics
@ -1223,6 +1225,51 @@ namespace sls {
return a.set_random(m_rand);
}
bool bv_eval::try_repair_sdiv(bvect const& e, bvval& a, bvval& b, unsigned i) {
bool sign_a = a.sign();
bool sign_b = b.sign();
bool sign_e = e.get(a.bw - 1);
// y = 0, x >= 0 -> -1
if (i == 0 && b.is_zero() && a.is_ones(e) && a.try_set(m_zero))
return true;
if (i == 0 && b.is_zero() && a.is_ones(e) && a.try_set_bit(a.bw - 1, false))
return true;
if (i == 1 && !sign_a && a.is_ones(e) && b.try_set(m_zero))
return true;
// y = 0, x < 0 -> 1
if (i == 0 && b.is_zero() && a.is_one(e) && a.try_set(m_minus_one))
return true;
if (i == 1 && sign_a && a.is_one(e) && b.try_set(m_zero))
return true;
// x = 0, y != 0 -> 0
if (i == 0 && a.is_zero(e) && !b.is_zero() && a.try_set(m_zero))
return true;
if (i == 1 && a.is_zero(e) && a.is_zero() && b.try_set_bit(ctx.rand(a.bw), true))
return true;
// e = x udiv y
// e = 0 => x != ones
// y = 0 => e = -1 // nothing to repair on a
// e != -1 => max(y) >=u e
//IF_VERBOSE(0, verbose_stream() << "sdiv " << e << " " << a << " " << b << "\n";);
// e = udiv(abs(x), abs(y))
// x > 0, y < 0 -> -e
// x < 0, y > 0 -> -e
// x > 0, y > 0 -> e
// x < 0, y < 0 -> e
return try_repair_udiv(e, a, b, i);
}
bool bv_eval::try_repair_bnot(bvect const& e, bvval& a) {
for (unsigned i = 0; i < a.nw; ++i)
m_tmp[i] = ~e[i];

View file

@ -110,6 +110,7 @@ namespace sls {
bool try_repair_lshr1(bvect const& e, bvval const& a, bvval& b);
bool try_repair_ashr0(bvect const& e, bvval& a, bvval const& b);
bool try_repair_ashr1(bvect const& e, bvval const& a, bvval& b);
bool try_repair_sdiv(bvect const& e, bvval& a, bvval& b, unsigned i);
bool try_repair_bit2bool(bvval& a, unsigned idx);
bool try_repair_udiv(bvect const& e, bvval& a, bvval& b, unsigned i);
bool try_repair_urem(bvect const& e, bvval& a, bvval& b, unsigned i);
@ -126,6 +127,7 @@ namespace sls {
bool try_repair_comp(bvect const& e, bvval& a, bvval& b, unsigned i);
bool try_repair_eq(bool is_true, bvval& a, bvval const& b);
bool try_repair_eq(app* e, unsigned i);
bool try_repair_int2bv(bvect const& e, expr* arg);
void add_p2_1(bvval const& a, bvect& t) const;

View file

@ -587,8 +587,16 @@ namespace sls {
#endif
#if 1
if (allow_costly_flips(mt))
if (allow_costly_flips(mt))
ctx.flip(v);
else if (false) {
sat::bool_var_set rotated;
unsigned budget = 100;
bool rot = ctx.try_rotate(v, rotated, budget);
(void)rot;
TRACE("bv", tout << "rotate " << v << " " << rot << " " << rotated << "\n";);
verbose_stream() << "rotate " << v << " " << rot << " " << rotated << "\n";
}
#endif
}

View file

@ -40,7 +40,7 @@ namespace sls {
expr_ref bv_terms::ensure_binary(expr* e) {
expr* x, * y;
expr_ref r(m);
if (bv.is_bv_sdiv(e, x, y) || bv.is_bv_sdiv0(e, x, y) || bv.is_bv_sdivi(e, x, y))
if (false && (bv.is_bv_sdiv(e, x, y) || bv.is_bv_sdiv0(e, x, y) || bv.is_bv_sdivi(e, x, y)))
r = mk_sdiv(x, y);
else if (bv.is_bv_smod(e, x, y) || bv.is_bv_smod0(e, x, y) || bv.is_bv_smodi(e, x, y))
r = mk_smod(x, y);

View file

@ -369,3 +369,8 @@ inline std::ostream& operator<<(std::ostream& out, indexed_uint_set const& s) {
for (unsigned i : s) out << i << " ";
return out;
}
inline std::ostream& operator<<(std::ostream& out, tracked_uint_set const& s) {
for (unsigned i : s) out << i << " ";
return out;
}