Skip to content

Commit 388b2f5

Browse files
n/a
1 parent ddf2d28 commit 388b2f5

9 files changed

+272
-200
lines changed

src/ast/bv_decl_plugin.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -942,3 +942,13 @@ app* bv_util::mk_int2bv(unsigned sz, expr* e) {
942942
parameter p(sz);
943943
return m_manager.mk_app(get_fid(), OP_INT2BV, 1, &p, 1, &e);
944944
}
945+
946+
app* bv_util::mk_bv_rotate_left(expr* arg, unsigned n) {
947+
parameter p(n);
948+
return m_manager.mk_app(get_fid(), OP_ROTATE_LEFT, 1, &p, 1, &arg);
949+
}
950+
951+
app* bv_util::mk_bv_rotate_right(expr* arg, unsigned n) {
952+
parameter p(n);
953+
return m_manager.mk_app(get_fid(), OP_ROTATE_RIGHT, 1, &p, 1, &arg);
954+
}

src/ast/bv_decl_plugin.h

+5
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,11 @@ class bv_util : public bv_recognizers {
546546
app * mk_bv2int(expr* e);
547547
app * mk_int2bv(unsigned sz, expr* e);
548548

549+
app* mk_bv_rotate_left(expr* arg1, expr* arg2) { return m_manager.mk_app(get_fid(), OP_EXT_ROTATE_LEFT, arg1, arg2); }
550+
app* mk_bv_rotate_right(expr* arg1, expr* arg2) { return m_manager.mk_app(get_fid(), OP_EXT_ROTATE_RIGHT, arg1, arg2); }
551+
app* mk_bv_rotate_left(expr* arg, unsigned n);
552+
app* mk_bv_rotate_right(expr* arg, unsigned n);
553+
549554
// TODO: all these binary ops commute (right?) but it'd be more logical to swap `n` & `m` in the `return`
550555
app * mk_bvsmul_no_ovfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BSMUL_NO_OVFL, n, m); }
551556
app * mk_bvsmul_no_udfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BSMUL_NO_UDFL, n, m); }

src/ast/sls/bv_sls.cpp

+40-34
Original file line numberDiff line numberDiff line change
@@ -46,46 +46,53 @@ namespace bv {
4646
m_eval.init_fixed(m_terms.assertions());
4747
}
4848

49+
std::pair<bool, app*> sls::next_to_repair() {
50+
app* e = nullptr;
51+
if (!m_repair_down.empty()) {
52+
unsigned index = m_rand(m_repair_down.size());
53+
e = m_terms.term(m_repair_down.elem_at(index));
54+
}
55+
else if (m_repair_up.empty()) {
56+
unsigned index = m_rand(m_repair_up.size());
57+
e = m_terms.term(m_repair_up.elem_at(index));
58+
}
59+
return { !m_repair_down.empty(), e };
60+
}
61+
4962
lbool sls::operator()() {
5063
// init and init_eval were invoked.
5164
unsigned& n = m_stats.m_moves;
5265
n = 0;
5366
for (; n < m_config.m_max_repairs && m.inc(); ++n) {
54-
if (!m_repair_down.empty()) {
55-
unsigned index = m_rand(m_repair_down.size());
56-
unsigned expr_id = m_repair_down.elem_at(index);
57-
auto e = m_terms.term(expr_id);
58-
IF_VERBOSE(20, verbose_stream() << "d " << mk_bounded_pp(e, m, 1) << "\n");
59-
if (eval_is_correct(e))
60-
m_repair_down.remove(expr_id);
67+
auto [down, e] = next_to_repair();
68+
if (!e)
69+
return l_true;
70+
IF_VERBOSE(20, verbose_stream() << (down?"d ":"u ") << mk_bounded_pp(e, m, 1) << "\n");
71+
if (eval_is_correct(e)) {
72+
if (down)
73+
m_repair_down.remove(e->get_id());
6174
else
62-
try_repair_down(e);
75+
m_repair_up.remove(e->get_id());
6376
}
64-
else if (!m_repair_up.empty()) {
65-
unsigned index = m_rand(m_repair_up.size());
66-
unsigned expr_id = m_repair_up.elem_at(index);
67-
auto e = m_terms.term(expr_id);
68-
IF_VERBOSE(20, verbose_stream() << "u " << mk_bounded_pp(e, m, 1) << "\n");
69-
if (eval_is_correct(e))
70-
m_repair_up.remove(expr_id);
71-
else
72-
try_repair_up(e);
77+
else if (down) {
78+
try_repair_down(e);
7379
}
74-
else
75-
return l_true;
80+
else
81+
try_repair_up(e);
7682
}
7783
return l_undef;
7884
}
7985

80-
bool sls::try_repair_down(app* e) {
86+
void sls::try_repair_down(app* e) {
8187
unsigned n = e->get_num_args();
82-
if (n == 0)
83-
return false;
84-
unsigned s = m_rand(n);
85-
for (unsigned i = 0; i < n; ++i)
86-
if (try_repair_down(e, (i + s) % n))
87-
return true;
88-
return false;
88+
if (n > 0) {
89+
unsigned s = m_rand(n);
90+
for (unsigned i = 0; i < n; ++i)
91+
if (try_repair_down(e, (i + s) % n))
92+
return;
93+
}
94+
m_repair_down.remove(e->get_id());
95+
m_repair_up.insert(e->get_id());
8996
}
9097

9198
bool sls::try_repair_down(app* e, unsigned i) {
@@ -99,17 +106,16 @@ namespace bv {
99106
return was_repaired;
100107
}
101108

102-
bool sls::try_repair_up(app* e) {
109+
void sls::try_repair_up(app* e) {
103110
m_repair_up.remove(e->get_id());
104111
if (m_terms.is_assertion(e)) {
105112
m_repair_down.insert(e->get_id());
106-
return false;
107113
}
108-
m_eval.repair_up(e);
109-
for (auto p : m_terms.parents(e))
110-
m_repair_up.insert(p->get_id());
111-
112-
return true;
114+
else {
115+
m_eval.repair_up(e);
116+
for (auto p : m_terms.parents(e))
117+
m_repair_up.insert(p->get_id());
118+
}
113119
}
114120

115121
bool sls::eval_is_correct(app* e) {

src/ast/sls/bv_sls.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,11 @@ namespace bv {
4949
random_gen m_rand;
5050
config m_config;
5151

52+
std::pair<bool, app*> next_to_repair();
5253

5354
bool eval_is_correct(app* e);
54-
bool try_repair_down(app* e);
55-
bool try_repair_up(app* e);
55+
void try_repair_down(app* e);
56+
void try_repair_up(app* e);
5657

5758
bool try_repair_down(app* e, unsigned i);
5859

src/ast/sls/bv_sls_eval.cpp

+20-17
Original file line numberDiff line numberDiff line change
@@ -343,16 +343,9 @@ namespace bv {
343343
}
344344
};
345345

346-
auto mk_rotate_left = [&](unsigned n) {
346+
auto mk_rotate_left = [&](unsigned n) {
347347
auto& a = wval0(e->get_arg(0));
348-
if (n == 0 || a.bw == 1)
349-
val.set(a.bits);
350-
else {
351-
for (unsigned i = a.bw - n; i < a.bw; ++i)
352-
val.set(val.bits, i + n - a.bw, a.get(a.bits, i));
353-
for (unsigned i = 0; i < a.bw - n; ++i)
354-
val.set(val.bits, i + a.bw - n, a.get(a.bits, i));
355-
}
348+
VERIFY(try_repair_rotate_left(a, val, a.bw - n));
356349
};
357350

358351
SASSERT(e->get_family_id() == bv.get_fid());
@@ -853,6 +846,7 @@ namespace bv {
853846
auto child = e->get_arg(i);
854847
auto ev = bval0(e);
855848
if (m.is_bool(child)) {
849+
SASSERT(!is_fixed0(child));
856850
auto bv = bval0(e->get_arg(1 - i));
857851
m_eval[child->get_id()] = ev == bv;
858852
return true;
@@ -863,12 +857,21 @@ namespace bv {
863857
if (ev)
864858
return a.try_set(b.bits);
865859
else {
866-
// pick random bit to differ
867-
for (unsigned i = 0; i < a.nw; ++i)
868-
m_tmp[i] = a.bits[i];
869-
unsigned idx = m_rand(a.bw);
870-
a.set(m_tmp, idx, !b.get(b.bits, idx));
871-
return a.try_set(m_tmp);
860+
// pick random bit to differ
861+
a.get(m_tmp);
862+
unsigned start = m_rand(a.bw);
863+
for (unsigned idx = 0; idx < a.bw; ++idx) {
864+
unsigned j = (idx + start) % a.bw;
865+
if (!a.get(a.fixed, j)) {
866+
a.set(m_tmp, idx, !b.get(b.bits, j));
867+
bool r = a.try_set(m_tmp);
868+
if (r)
869+
return true;
870+
a.set(m_tmp, j, b.get(b.bits, j));
871+
}
872+
}
873+
// could be due to bounds?
874+
return false;
872875
}
873876
}
874877
return false;
@@ -1107,9 +1110,9 @@ namespace bv {
11071110
return false;
11081111
}
11091112

1110-
bool sls_eval::try_repair_rotate_left(bvval const& e, bvval& a, unsigned n) {
1113+
bool sls_eval::try_repair_rotate_left(bvval const& e, bvval& a, unsigned n) const {
11111114
// a := rotate_right(e, n)
1112-
n = (n % a.bw) - n;
1115+
n = (a.bw - n) % a.bw;
11131116
for (unsigned i = a.bw - n; i < a.bw; ++i)
11141117
a.set(m_tmp, i + n - a.bw, e.get(e.bits, i));
11151118
for (unsigned i = 0; i < a.bw - n; ++i)

src/ast/sls/bv_sls_eval.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,9 @@ namespace bv {
8888
bool try_repair_smod(bvval const& e, bvval& a, bvval& b, unsigned i);
8989
bool try_repair_urem(bvval const& e, bvval& a, bvval& b, unsigned i);
9090
bool try_repair_srem(bvval const& e, bvval& a, bvval& b, unsigned i);
91-
bool try_repair_rotate_left(bvval const& e, bvval& a, unsigned n);
91+
bool try_repair_rotate_left(bvval const& e, bvval& a, unsigned n) const;
9292
bool try_repair_rotate_left(bvval const& e, bvval& a, bvval& b, unsigned i);
9393

94-
9594
sls_valuation& wval0(app* e, unsigned i) { return wval0(e->get_arg(i)); }
9695

9796
void wval1(app* e, sls_valuation& val) const;

src/ast/sls/sls_valuation.cpp

+53-19
Original file line numberDiff line numberDiff line change
@@ -33,26 +33,27 @@ namespace bv {
3333
for (unsigned i = 0; i < nw; ++i)
3434
lo[i] = 0, hi[i] = 0, bits[i] = 0, fixed[i] = 0;
3535
for (unsigned i = bw; i < 8 * sizeof(digit_t) * nw; ++i)
36-
set(fixed, i, true);
36+
set(fixed, i, false);
3737
}
3838

3939
sls_valuation::~sls_valuation() {
4040
}
4141

42-
bool sls_valuation::is_feasible() const {
43-
return true;
44-
mpn_manager m;
45-
unsigned nb = (bw + 7) / 8;
46-
auto c = m.compare(lo.data(), nb, hi.data(), nb);
42+
bool sls_valuation::in_range(svector<digit_t> const& bits) const {
43+
mpn_manager m;
44+
auto c = m.compare(lo.data(), nw, hi.data(), nw);
45+
// full range
4746
if (c == 0)
4847
return true;
48+
// lo < hi: then lo <= bits & bits < hi
4949
if (c < 0)
50-
return
51-
m.compare(lo.data(), nb, bits.data(), nb) <= 0 &&
52-
m.compare(bits.data(), nb, hi.data(), nb) < 0;
53-
return
54-
m.compare(lo.data(), nb, bits.data(), nb) <= 0 ||
55-
m.compare(bits.data(), nb, hi.data(), nb) < 0;
50+
return
51+
m.compare(lo.data(), nw, bits.data(), nw) <= 0 &&
52+
m.compare(bits.data(), nw, hi.data(), nw) < 0;
53+
// hi < lo: bits < hi or lo <= bits
54+
return
55+
m.compare(lo.data(), nw, bits.data(), nw) <= 0 ||
56+
m.compare(bits.data(), nw, hi.data(), nw) < 0;
5657
}
5758

5859
bool sls_valuation::eq(svector<digit_t> const& other) const {
@@ -65,11 +66,34 @@ namespace bv {
6566
return true;
6667
}
6768

69+
bool sls_valuation::gt(svector<digit_t> const& a, svector<digit_t> const& b) const {
70+
mpn_manager m;
71+
return m.compare(a.data(), nw, b.data(), nw) > 0;
72+
}
73+
6874
void sls_valuation::clear_overflow_bits(svector<digit_t>& bits) const {
6975
for (unsigned i = bw; i < nw * sizeof(digit_t) * 8; ++i)
7076
set(bits, i, false);
7177
}
7278

79+
bool sls_valuation::get_below(svector<digit_t> const& src, svector<digit_t>& dst) {
80+
for (unsigned i = 0; i < nw; ++i)
81+
dst[i] = (src[i] & ~fixed[i]) | (fixed[i] & bits[i]);
82+
for (unsigned i = 0; i < nw; ++i)
83+
dst[i] = fixed[i] & bits[i];
84+
if (gt(dst, src))
85+
return false;
86+
if (!in_range(dst)) {
87+
// lo < hi:
88+
// set dst to lo, except for fixed bits
89+
//
90+
if (gt(hi, lo)) {
91+
92+
}
93+
}
94+
return true;
95+
}
96+
7397
void sls_valuation::set_value(svector<digit_t>& bits, rational const& n) {
7498
for (unsigned i = 0; i < bw; ++i)
7599
set(bits, i, n.get_bit(i));
@@ -94,11 +118,16 @@ namespace bv {
94118
set(bits, i, true);
95119
}
96120

97-
bool sls_valuation::can_set(svector<digit_t> const& new_bits) const {
121+
//
122+
// new_bits != bits => ~fixed
123+
// 0 = (new_bits ^ bits) & fixed
124+
// also check that new_bits are in range
125+
//
126+
bool sls_valuation::can_set(svector<digit_t> const& new_bits) const {
98127
for (unsigned i = 0; i < nw; ++i)
99-
if (bits[i] != ((new_bits[i] & ~fixed[i]) | (bits[i] & fixed[i])))
100-
return true;
101-
return false;
128+
if (0 != ((new_bits[i] ^ bits[i]) & fixed[i]))
129+
return false;
130+
return in_range(new_bits);
102131
}
103132

104133
unsigned sls_valuation::to_nat(svector<digit_t> const& d, unsigned max_n) {
@@ -124,10 +153,15 @@ namespace bv {
124153
h = mod(h, rational::power_of_two(bw));
125154
if (h == l)
126155
return;
127-
set_value(this->lo, l);
128-
set_value(this->hi, h);
156+
if (eq(lo, hi)) {
157+
set_value(lo, l);
158+
set_value(hi, h);
159+
return;
160+
}
161+
129162
// TODO: intersect with previous range, if any
130-
163+
set_value(lo, l);
164+
set_value(hi, h);
131165
}
132166

133167
}

src/ast/sls/sls_valuation.h

+11-10
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,10 @@ Module Name:
2828
namespace bv {
2929

3030
struct sls_valuation {
31-
unsigned bw; // bit-width
32-
unsigned nw; // num words
33-
svector<digit_t> lo, hi; // range assignment to bit-vector, as wrap-around interval
31+
unsigned bw; // bit-width
32+
unsigned nw; // num words
33+
svector<digit_t> lo, hi; // range assignment to bit-vector, as wrap-around interval
3434
svector<digit_t> bits, fixed; // bit assignment and don't care bit
35-
bool is_feasible() const; // the current bit-evaluation is between lo and hi.
3635
sls_valuation(unsigned bw);
3736
~sls_valuation();
3837

@@ -44,17 +43,15 @@ namespace bv {
4443
void add_range(rational lo, rational hi);
4544
void set1(svector<digit_t>& bits);
4645

47-
4846
void clear_overflow_bits(svector<digit_t>& bits) const;
47+
bool in_range(svector<digit_t> const& bits) const;
4948
bool can_set(svector<digit_t> const& bits) const;
5049

5150
bool eq(sls_valuation const& other) const { return eq(other.bits); }
5251

53-
bool eq(svector<digit_t> const& other) const;
54-
55-
bool gt(svector<digit_t> const& a, svector<digit_t> const& b) const {
56-
return 0 > memcmp(a.data(), b.data(), num_bytes());
57-
}
52+
bool eq(svector<digit_t> const& other) const { return eq(other, bits); }
53+
bool eq(svector<digit_t> const& a, svector<digit_t> const& b) const;
54+
bool gt(svector<digit_t> const& a, svector<digit_t> const& b) const;
5855

5956
bool is_zero() const { return is_zero(bits); }
6057
bool is_zero(svector<digit_t> const& a) const {
@@ -79,6 +76,10 @@ namespace bv {
7976
return i;
8077
}
8178

79+
// retrieve number at or below src which is feasible
80+
// with respect to fixed, lo, hi.
81+
bool get_below(svector<digit_t> const& src, svector<digit_t>& dst);
82+
8283
bool try_set(svector<digit_t> const& src) {
8384
if (!can_set(src))
8485
return false;

0 commit comments

Comments
 (0)