mirror of
https://github.com/Z3Prover/z3
synced 2025-04-11 03:33:35 +00:00
605 lines
18 KiB
C++
605 lines
18 KiB
C++
/*++
|
|
Copyright (c) 2011 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
bv2int_rewriter.cpp
|
|
|
|
Abstract:
|
|
|
|
Basic rewriting rules for bv2int propagation.
|
|
|
|
Author:
|
|
|
|
Nikolaj (nbjorner) 2011-05-05
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
#include "bv2int_rewriter.h"
|
|
#include "rewriter_def.h"
|
|
#include "ast_pp.h"
|
|
|
|
void bv2int_rewriter_ctx::update_params(params_ref const& p) {
|
|
m_max_size = p.get_uint(":max-bv-size", UINT_MAX);
|
|
}
|
|
|
|
struct lt_rational {
|
|
bool operator()(rational const& a, rational const& b) const { return a < b; }
|
|
};
|
|
|
|
void bv2int_rewriter_ctx::collect_power2(goal const& s) {
|
|
ast_manager& m = m_trail.get_manager();
|
|
arith_util arith(m);
|
|
bv_util bv(m);
|
|
|
|
for (unsigned j = 0; j < s.size(); ++j) {
|
|
expr* f = s.form(j);
|
|
if (!m.is_or(f)) continue;
|
|
unsigned sz = to_app(f)->get_num_args();
|
|
expr* x, *y, *v = 0;
|
|
rational n;
|
|
vector<rational> bounds;
|
|
bool is_int, ok = true;
|
|
|
|
for (unsigned i = 0; ok && i < sz; ++i) {
|
|
expr* e = to_app(f)->get_arg(i);
|
|
if (!m.is_eq(e, x, y)) {
|
|
ok = false;
|
|
break;
|
|
}
|
|
if (arith.is_numeral(y, n, is_int) && is_int &&
|
|
(x == v || v == 0)) {
|
|
v = x;
|
|
bounds.push_back(n);
|
|
}
|
|
else if (arith.is_numeral(x, n, is_int) && is_int &&
|
|
(y == v || v == 0)) {
|
|
v = y;
|
|
bounds.push_back(n);
|
|
}
|
|
else {
|
|
ok = false;
|
|
break;
|
|
}
|
|
}
|
|
if (!ok || !v) continue;
|
|
SASSERT(!bounds.empty());
|
|
lt_rational lt;
|
|
// lt is a total order on rationals.
|
|
std::sort(bounds.begin(), bounds.end(), lt);
|
|
rational p(1);
|
|
unsigned num_bits = 0;
|
|
for (unsigned i = 0; ok && i < bounds.size(); ++i) {
|
|
ok = (p == bounds[i]);
|
|
p *= rational(2);
|
|
++num_bits;
|
|
}
|
|
if (!ok) continue;
|
|
unsigned log2 = 0;
|
|
for (unsigned i = 1; i <= num_bits; i *= 2) ++log2;
|
|
if(log2 == 0) continue;
|
|
expr* logx = m.mk_fresh_const("log2_v", bv.mk_sort(log2));
|
|
logx = bv.mk_zero_extend(num_bits - log2, logx);
|
|
m_trail.push_back(logx);
|
|
TRACE("bv2int_rewriter", tout << mk_pp(v, m) << " |-> " << mk_pp(logx, m) << "\n";);
|
|
m_power2.insert(v, logx);
|
|
}
|
|
}
|
|
|
|
bool bv2int_rewriter_ctx::is_power2(expr* x, expr*& log_x) {
|
|
return m_power2.find(x, log_x);
|
|
}
|
|
|
|
bv2int_rewriter::bv2int_rewriter(ast_manager & m, bv2int_rewriter_ctx& ctx)
|
|
:m_manager(m), m_ctx(ctx), m_bv(m), m_arith(m) {
|
|
}
|
|
|
|
|
|
br_status bv2int_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
|
|
if(f->get_family_id() == m_arith.get_family_id()) {
|
|
switch (f->get_decl_kind()) {
|
|
case OP_NUM: return BR_FAILED;
|
|
case OP_LE: SASSERT(num_args == 2); return mk_le(args[0], args[1], result);
|
|
case OP_GE: SASSERT(num_args == 2); return mk_ge(args[0], args[1], result);
|
|
case OP_LT: SASSERT(num_args == 2); return mk_lt(args[0], args[1], result);
|
|
case OP_GT: SASSERT(num_args == 2); return mk_gt(args[0], args[1], result);
|
|
case OP_ADD: return mk_add(num_args, args, result);
|
|
case OP_MUL: return mk_mul(num_args, args, result);
|
|
case OP_SUB: return mk_sub(num_args, args, result);
|
|
case OP_DIV: return BR_FAILED;
|
|
case OP_IDIV: SASSERT(num_args == 2); return mk_idiv(args[0], args[1], result);
|
|
case OP_MOD: SASSERT(num_args == 2); return mk_mod(args[0], args[1], result);
|
|
case OP_REM: SASSERT(num_args == 2); return mk_rem(args[0], args[1], result);
|
|
case OP_UMINUS: SASSERT(num_args == 1); return mk_uminus(args[0], result);
|
|
case OP_TO_REAL: return BR_FAILED;
|
|
case OP_TO_INT: return BR_FAILED;
|
|
case OP_IS_INT: return BR_FAILED;
|
|
default:
|
|
return BR_FAILED;
|
|
}
|
|
}
|
|
if (f->get_family_id() == m().get_basic_family_id()) {
|
|
switch (f->get_decl_kind()) {
|
|
case OP_EQ: SASSERT(num_args == 2); return mk_eq(args[0], args[1], result);
|
|
case OP_ITE: SASSERT(num_args == 3); return mk_ite(args[0], args[1], args[2], result);
|
|
default: return BR_FAILED;
|
|
}
|
|
}
|
|
return BR_FAILED;
|
|
}
|
|
|
|
br_status bv2int_rewriter::mk_le(expr * s, expr * t, expr_ref & result) {
|
|
expr_ref s1(m()), t1(m()), s2(m()), t2(m());
|
|
if (is_bv2int(s, s1) && is_bv2int(t, t1)) {
|
|
align_sizes(s1, t1, false);
|
|
result = m_bv.mk_ule(s1, t1);
|
|
return BR_DONE;
|
|
}
|
|
if (is_bv2int_diff(s, s1, s2) && is_bv2int_diff(t, t1, t2)) {
|
|
// s1 - s2 <= t1 - t2
|
|
// <=>
|
|
// s1 + t2 <= t1 + s2
|
|
//
|
|
s1 = mk_bv_add(s1, t2, false);
|
|
t1 = mk_bv_add(t1, s2, false);
|
|
align_sizes(s1, t1, false);
|
|
result = m_bv.mk_ule(s1, t1);
|
|
return BR_DONE;
|
|
}
|
|
if (is_sbv2int(s, s1) && is_sbv2int(t, t1)) {
|
|
align_sizes(s1, t1, true);
|
|
result = m_bv.mk_sle(s1, t1);
|
|
return BR_DONE;
|
|
}
|
|
return BR_FAILED;
|
|
}
|
|
|
|
br_status bv2int_rewriter::mk_lt(expr * arg1, expr * arg2, expr_ref & result) {
|
|
result = m().mk_not(m_arith.mk_le(arg2, arg1));
|
|
return BR_REWRITE2;
|
|
}
|
|
|
|
br_status bv2int_rewriter::mk_ge(expr * arg1, expr * arg2, expr_ref & result) {
|
|
return mk_le(arg2, arg1, result);
|
|
}
|
|
|
|
br_status bv2int_rewriter::mk_gt(expr * arg1, expr * arg2, expr_ref & result) {
|
|
result = m().mk_not(m_arith.mk_le(arg1, arg2));
|
|
return BR_REWRITE2;
|
|
}
|
|
|
|
br_status bv2int_rewriter::mk_ite(expr* c, expr* s, expr* t, expr_ref& result) {
|
|
expr_ref s1(m()), t1(m());
|
|
if (is_bv2int(s, s1) && is_bv2int(t, t1)) {
|
|
align_sizes(s1, t1, false);
|
|
result = m_bv.mk_bv2int(m().mk_ite(c, s1, t1));
|
|
return BR_DONE;
|
|
}
|
|
|
|
if (is_sbv2int(s, s1) && is_sbv2int(t, t1)) {
|
|
align_sizes(s1, t1, true);
|
|
result = mk_sbv2int(m().mk_ite(c, s1, t1));
|
|
return BR_DONE;
|
|
}
|
|
return BR_FAILED;
|
|
}
|
|
|
|
br_status bv2int_rewriter::mk_eq(expr * s, expr * t, expr_ref & result) {
|
|
expr_ref s1(m()), t1(m()), s2(m()), t2(m());
|
|
if (is_bv2int(s, s1) && is_bv2int(t, t1)) {
|
|
align_sizes(s1, t1, false);
|
|
result = m().mk_eq(s1, t1);
|
|
return BR_DONE;
|
|
}
|
|
if (is_bv2int_diff(s, s1, s2) && is_bv2int_diff(t, t1, t2)) {
|
|
s1 = mk_bv_add(s1, t2, false);
|
|
t1 = mk_bv_add(s2, t1, false);
|
|
align_sizes(s1, t1, false);
|
|
result = m().mk_eq(s1, t1);
|
|
return BR_DONE;
|
|
}
|
|
if (is_sbv2int(s, s1) && is_sbv2int(t, t1)) {
|
|
align_sizes(s1, t1, true);
|
|
result = m().mk_eq(s1, t1);
|
|
return BR_DONE;
|
|
}
|
|
return BR_FAILED;
|
|
}
|
|
|
|
|
|
br_status bv2int_rewriter::mk_idiv(expr * arg1, expr * arg2, expr_ref & result) {
|
|
// TBD
|
|
return BR_FAILED;
|
|
}
|
|
|
|
br_status bv2int_rewriter::mk_mod(expr * s, expr * t, expr_ref & result) {
|
|
expr_ref s1(m()), s2(m()), t1(m());
|
|
if (is_bv2int(s, s1) && is_bv2int(t, t1)) {
|
|
align_sizes(s1, t1, false);
|
|
result = m_bv.mk_bv2int(m_bv.mk_bv_urem(s1, t1));
|
|
return BR_DONE;
|
|
}
|
|
|
|
//
|
|
// (s1 - s2) mod t1 = (s1 + (t1 - (s2 mod t1))) mod t1
|
|
//
|
|
if (is_bv2int_diff(s, s1, s2) && is_bv2int(t, t1)) {
|
|
expr_ref u1(m());
|
|
align_sizes(s1, t1, false);
|
|
u1 = m_bv.mk_bv_urem(s1, t1);
|
|
u1 = m_bv.mk_bv_sub(t1, u1);
|
|
u1 = mk_bv_add(s1, u1, false);
|
|
align_sizes(u1, t1, false);
|
|
result = m_bv.mk_bv2int(m_bv.mk_bv_urem(u1, t1));
|
|
return BR_DONE;
|
|
}
|
|
|
|
#if 0
|
|
// TBD: check semantics
|
|
if (is_sbv2int(s, s1) && is_sbv2int(t, t1)) {
|
|
align_sizes(s1, t1, true);
|
|
result = mk_sbv2int(m_bv.mk_bv_srem(s1, t1));
|
|
return BR_DONE;
|
|
}
|
|
#endif
|
|
return BR_FAILED;
|
|
}
|
|
|
|
|
|
br_status bv2int_rewriter::mk_rem(expr * arg1, expr * arg2, expr_ref & result) {
|
|
// TBD
|
|
return BR_FAILED;
|
|
}
|
|
|
|
br_status bv2int_rewriter::mk_uminus(expr * s, expr_ref & result) {
|
|
expr_ref s1(m()), s2(m());
|
|
if (is_bv2int_diff(s, s1, s2)) {
|
|
result = m_arith.mk_sub(m_bv.mk_bv2int(s2), m_bv.mk_bv2int(s1));
|
|
return BR_DONE;
|
|
}
|
|
if (is_sbv2int(s, s1)) {
|
|
result = mk_sbv2int(m_bv.mk_bv_neg(s1));
|
|
return BR_DONE;
|
|
}
|
|
return BR_FAILED;
|
|
}
|
|
|
|
|
|
br_status bv2int_rewriter::mk_add(unsigned num_args, expr * const* args, expr_ref& result) {
|
|
br_status r = BR_DONE;
|
|
SASSERT(num_args > 0);
|
|
result = args[0];
|
|
for (unsigned i = 1; r == BR_DONE && i < num_args; ++i) {
|
|
r = mk_add(result, args[i], result);
|
|
}
|
|
return r;
|
|
}
|
|
|
|
void bv2int_rewriter::align_sizes(expr_ref& s, expr_ref& t, bool is_signed) {
|
|
unsigned sz1 = m_bv.get_bv_size(s);
|
|
unsigned sz2 = m_bv.get_bv_size(t);
|
|
if (sz1 > sz2 && is_signed) {
|
|
t = mk_extend(sz1-sz2, t, true);
|
|
}
|
|
if (sz1 > sz2 && !is_signed) {
|
|
t = mk_extend(sz1-sz2, t, false);
|
|
}
|
|
if (sz1 < sz2 && is_signed) {
|
|
s = mk_extend(sz2-sz1, s, true);
|
|
}
|
|
if (sz1 < sz2 && !is_signed) {
|
|
s = mk_extend(sz2-sz1, s, false);
|
|
}
|
|
}
|
|
|
|
|
|
bool bv2int_rewriter::is_zero(expr* n) {
|
|
rational r;
|
|
unsigned sz;
|
|
return m_bv.is_numeral(n, r, sz) && r.is_zero();
|
|
}
|
|
|
|
expr* bv2int_rewriter::mk_bv_add(expr* s, expr* t, bool is_signed) {
|
|
SASSERT(m_bv.is_bv(s));
|
|
SASSERT(m_bv.is_bv(t));
|
|
|
|
if (is_zero(s)) {
|
|
return t;
|
|
}
|
|
if (is_zero(t)) {
|
|
return s;
|
|
}
|
|
expr_ref s1(s, m()), t1(t, m());
|
|
align_sizes(s1, t1, is_signed);
|
|
s1 = mk_extend(1, s1, is_signed);
|
|
t1 = mk_extend(1, t1, is_signed);
|
|
return m_bv.mk_bv_add(s1, t1);
|
|
}
|
|
|
|
|
|
br_status bv2int_rewriter::mk_add(expr* s, expr* t, expr_ref& result) {
|
|
expr_ref s1(m()), t1(m()), s2(m()), t2(m());
|
|
if (is_bv2int(s, s1) && is_bv2int(t, t1)) {
|
|
result = m_bv.mk_bv2int(mk_bv_add(s1, t1, false));
|
|
return BR_DONE;
|
|
}
|
|
if (is_bv2int_diff(s, s1, s2) && is_bv2int_diff(t, t1, t2)) {
|
|
// s1 - s2 + t1 - t2
|
|
// =
|
|
// s1 + t1 - (s2 + t2)
|
|
//
|
|
t1 = m_bv.mk_bv2int(mk_bv_add(s1, t1, false));
|
|
t2 = m_bv.mk_bv2int(mk_bv_add(s2, t2, false));
|
|
result = m_arith.mk_sub(t1, t2);
|
|
return BR_DONE;
|
|
}
|
|
if (is_sbv2int(s, s1) && is_sbv2int(t, t1)) {
|
|
result = mk_sbv2int(mk_bv_add(s1, t1, true));
|
|
return BR_DONE;
|
|
}
|
|
return BR_FAILED;
|
|
}
|
|
|
|
br_status bv2int_rewriter::mk_mul(unsigned num_args, expr * const* args, expr_ref& result) {
|
|
br_status r = BR_DONE;
|
|
SASSERT(num_args > 0);
|
|
result = args[0];
|
|
for (unsigned i = 1; r == BR_DONE && i < num_args; ++i) {
|
|
r = mk_mul(result, args[i], result);
|
|
}
|
|
return r;
|
|
}
|
|
|
|
expr* bv2int_rewriter::mk_bv_mul(expr* s, expr* t, bool is_signed) {
|
|
SASSERT(m_bv.is_bv(s));
|
|
SASSERT(m_bv.is_bv(t));
|
|
if (is_zero(s)) {
|
|
return s;
|
|
}
|
|
if (is_zero(t)) {
|
|
return t;
|
|
}
|
|
rational r;
|
|
unsigned sz;
|
|
if (m_bv.is_numeral(s, r, sz) && r.is_one()) {
|
|
return t;
|
|
}
|
|
if (m_bv.is_numeral(t, r, sz) && r.is_one()) {
|
|
return s;
|
|
}
|
|
expr_ref s1(s, m()), t1(t, m());
|
|
align_sizes(s1, t1, is_signed);
|
|
unsigned n = m_bv.get_bv_size(t1);
|
|
unsigned max_bits = m_ctx.get_max_num_bits();
|
|
bool add_side_conds = 2*n > max_bits;
|
|
if (n >= max_bits) {
|
|
//
|
|
}
|
|
else if (2*n > max_bits) {
|
|
s1 = mk_extend(max_bits-n, s1, is_signed);
|
|
t1 = mk_extend(max_bits-n, t1, is_signed);
|
|
}
|
|
else {
|
|
s1 = mk_extend(n, s1, is_signed);
|
|
t1 = mk_extend(n, t1, is_signed);
|
|
}
|
|
if (add_side_conds) {
|
|
if (is_signed) {
|
|
m_ctx.add_side_condition(m_bv.mk_bvsmul_no_ovfl(s1, t1));
|
|
m_ctx.add_side_condition(m_bv.mk_bvsmul_no_udfl(s1, t1));
|
|
}
|
|
else {
|
|
m_ctx.add_side_condition(m_bv.mk_bvumul_no_ovfl(s1, t1));
|
|
}
|
|
}
|
|
return m_bv.mk_bv_mul(s1, t1);
|
|
}
|
|
|
|
|
|
br_status bv2int_rewriter::mk_mul(expr* s, expr* t, expr_ref& result) {
|
|
expr_ref s1(m()), s2(m()), t1(m()), t2(m());
|
|
if ((is_shl1(s, s1) && is_bv2int(t, t1)) ||
|
|
(is_shl1(t, s1) && is_bv2int(s, t1))) {
|
|
unsigned n = m_bv.get_bv_size(s1);
|
|
unsigned m = m_bv.get_bv_size(t1);
|
|
s1 = mk_extend(m, s1, false);
|
|
t1 = mk_extend(n, t1, false);
|
|
result = m_bv.mk_bv2int(m_bv.mk_bv_shl(t1, s1));
|
|
return BR_DONE;
|
|
}
|
|
if (is_bv2int(s, s1) && is_bv2int(t, t1)) {
|
|
result = m_bv.mk_bv2int(mk_bv_mul(s1, t1, false));
|
|
return BR_DONE;
|
|
}
|
|
if ((is_bv2int(s, s1) && is_bv2int_diff(t, t1, t2)) ||
|
|
(is_bv2int(t, s1) && is_bv2int_diff(s, t1, t2))) {
|
|
t1 = m_bv.mk_bv2int(mk_bv_mul(s1, t1, false));
|
|
t2 = m_bv.mk_bv2int(mk_bv_mul(s1, t2, false));
|
|
result = m_arith.mk_sub(t1, t2);
|
|
return BR_DONE;
|
|
}
|
|
if (is_sbv2int(s, s1) && is_sbv2int(t, t1)) {
|
|
result = mk_sbv2int(mk_bv_mul(s1, t1, true));
|
|
return BR_DONE;
|
|
}
|
|
return BR_FAILED;
|
|
}
|
|
|
|
br_status bv2int_rewriter::mk_sub(unsigned num_args, expr * const* args, expr_ref& result) {
|
|
br_status r = BR_DONE;
|
|
SASSERT(num_args > 0);
|
|
result = args[0];
|
|
for (unsigned i = 1; r == BR_DONE && i < num_args; ++i) {
|
|
r = mk_sub(result, args[i], result);
|
|
}
|
|
return r;
|
|
}
|
|
|
|
br_status bv2int_rewriter::mk_sub(expr* s, expr* t, expr_ref& result) {
|
|
expr_ref s1(m()), t1(m()), s2(m()), t2(m());
|
|
if (is_bv2int_diff(s, s1, s2) && is_bv2int_diff(t, t1, t2)) {
|
|
// s1 - s2 - (t1 - t2)
|
|
// =
|
|
// s1 + t2 - (t1 + s2)
|
|
//
|
|
s1 = m_bv.mk_bv2int(mk_bv_add(s1, t2, false));
|
|
s2 = m_bv.mk_bv2int(mk_bv_add(s2, t1, false));
|
|
result = m_arith.mk_sub(s1, s2);
|
|
return BR_DONE;
|
|
}
|
|
if (is_sbv2int(s, s1) && is_sbv2int(t, t1)) {
|
|
align_sizes(s1, t1, true);
|
|
s1 = m_bv.mk_sign_extend(1, s1);
|
|
t1 = m_bv.mk_sign_extend(1, t1);
|
|
result = mk_sbv2int(m_bv.mk_bv_sub(s1, t1));
|
|
return BR_DONE;
|
|
}
|
|
return BR_FAILED;
|
|
}
|
|
|
|
bool bv2int_rewriter::is_bv2int(expr* n, expr_ref& s) {
|
|
rational k;
|
|
bool is_int;
|
|
if (m_bv.is_bv2int(n)) {
|
|
s = to_app(n)->get_arg(0);
|
|
return true;
|
|
}
|
|
if (m_arith.is_numeral(n, k, is_int) && is_int && !k.is_neg()) {
|
|
unsigned sz = k.get_num_bits();
|
|
s = m_bv.mk_numeral(k, m_bv.mk_sort(sz));
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool bv2int_rewriter::is_shl1(expr* n, expr_ref& s) {
|
|
expr* s1, *s2;
|
|
rational r;
|
|
unsigned bv_size;
|
|
if(m_bv.is_bv2int(n, s2) &&
|
|
m_bv.is_bv_shl(s2, s1, s2) &&
|
|
m_bv.is_numeral(s1, r, bv_size) &&
|
|
r.is_one()) {
|
|
s = s2;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool bv2int_rewriter::is_bv2int_diff(expr* n, expr_ref& s, expr_ref& t) {
|
|
if (is_bv2int(n, s)) {
|
|
t = m_bv.mk_numeral(0, 1);
|
|
return true;
|
|
}
|
|
rational k;
|
|
bool is_int;
|
|
if (m_arith.is_numeral(n, k, is_int) && is_int) {
|
|
SASSERT(k.is_neg());
|
|
k.neg();
|
|
unsigned sz = k.get_num_bits();
|
|
t = m_bv.mk_numeral(k, m_bv.mk_sort(sz));
|
|
s = m_bv.mk_numeral(0, 1);
|
|
return true;
|
|
}
|
|
//
|
|
// bv2int(a) - bv2int(b)
|
|
//
|
|
expr *e1, *e2;
|
|
if (m_arith.is_sub(n, e1, e2) &&
|
|
is_bv2int(e1, s) &&
|
|
is_bv2int(e2, t)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool bv2int_rewriter::is_sbv2int(expr* n, expr_ref& s) {
|
|
if (is_bv2int(n, s)) {
|
|
s = m_bv.mk_zero_extend(1, s);
|
|
return true;
|
|
}
|
|
expr_ref u1(m()), u2(m());
|
|
if (is_bv2int_diff(n, u1, u2)) {
|
|
align_sizes(u1, u2, false);
|
|
u1 = mk_extend(1, u1, false);
|
|
u2 = mk_extend(1, u2, false);
|
|
s = m_bv.mk_bv_sub(u1, u2);
|
|
return true;
|
|
}
|
|
// ite(bv1 == b[n-1:n-1], bv2int(b[0:n-2]) - 2^{n-1}, bv2int(b[0:n-2]))
|
|
expr* c, *t, *e1, *c1, *c2, *c3, *t1, *t2, *e2, *e3;
|
|
rational k;
|
|
bool is_int;
|
|
unsigned lo, hi, lo1, hi1, sz;
|
|
|
|
if (m().is_ite(n, c, t, e1) &&
|
|
m().is_eq(c, c1, c2) &&
|
|
m_bv.is_numeral(c1, k, sz) && k.is_one() && sz == 1 &&
|
|
m_bv.is_extract(c2, lo, hi, c3) &&
|
|
lo == hi && lo == m_bv.get_bv_size(c3) - 1 &&
|
|
m_arith.is_sub(t, t1, t2) &&
|
|
e1 == t1 &&
|
|
m_bv.is_bv2int(e1, e2) &&
|
|
m_bv.is_extract(e2, lo1, hi1, e3) &&
|
|
lo1 == 0 && hi1 == hi-1 &&
|
|
m_arith.is_numeral(t2, k, is_int) && is_int &&
|
|
k == m_bv.power_of_two(hi)
|
|
) {
|
|
s = e3;
|
|
return true;
|
|
}
|
|
|
|
#if 0
|
|
// bv2int(b[0:n-2]) - ite(bv1 == b[n-1:n-1], 2^{n-1}, 0)
|
|
if (m().is_sub(n, e1, e2) &&
|
|
m_bv.is_bv2int(e1, e3) &&
|
|
m_bv.is_extract(e3, lo, hi, e4) &&
|
|
lo == 0 && hi == m_bv.get_bv_size(e4) - 2 &&
|
|
m().is_ite(e2, t1, t2, t3) &&
|
|
m().is_eq(t1, c1, c2) &&
|
|
m_bv.is_numeral(c1, k, sz) && k.is_one() && sz == 1 &&
|
|
m_bv.is_extract(c2, lo1, hi1, c3) && lo1 == h1 + 1 && hi1 == lo1 &&
|
|
c3 == e4 &&
|
|
m_arith.is_numeral(t2, )) {
|
|
|
|
}
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
expr* bv2int_rewriter::mk_sbv2int(expr* b) {
|
|
//
|
|
// ite(bit1 = b[n-1:n-1], bv2int(b[0:n-2]) - 2^{n-1}, bv2int(b[0:n-2]))
|
|
//
|
|
expr* bv1 = m_bv.mk_numeral(1, 1);
|
|
unsigned n = m_bv.get_bv_size(b);
|
|
expr* c = m().mk_eq(bv1, m_bv.mk_extract(n-1, n-1, b));
|
|
expr* e = m_bv.mk_bv2int(m_bv.mk_extract(n-2, 0, b));
|
|
expr* t = m_arith.mk_sub(e, m_arith.mk_numeral(power(rational(2), n-1), true));
|
|
return m().mk_ite(c, t, e);
|
|
}
|
|
|
|
expr* bv2int_rewriter::mk_extend(unsigned sz, expr* b, bool is_signed) {
|
|
if (sz == 0) {
|
|
return b;
|
|
}
|
|
rational r;
|
|
unsigned bv_sz;
|
|
if (is_signed) {
|
|
return m_bv.mk_sign_extend(sz, b);
|
|
}
|
|
else if (m_bv.is_numeral(b, r, bv_sz)) {
|
|
return m_bv.mk_numeral(r, bv_sz + sz);
|
|
}
|
|
else {
|
|
return m_bv.mk_zero_extend(sz, b);
|
|
}
|
|
}
|
|
|
|
template class rewriter_tpl<bv2int_rewriter_cfg>;
|
|
|
|
|
|
|
|
|