Skip to content

Commit 1cf008d

Browse files
updates
1 parent bd323d6 commit 1cf008d

File tree

4 files changed

+218
-32
lines changed

4 files changed

+218
-32
lines changed

src/ast/sls/bv_sls.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ namespace bv {
7979

8080
bool sls::try_repair_down(app* e) {
8181
unsigned n = e->get_num_args();
82+
if (n == 0)
83+
return false;
8284
unsigned s = m_rand(n);
8385
for (unsigned i = 0; i < n; ++i)
8486
if (try_repair_down(e, (i + s) % n))
@@ -114,7 +116,7 @@ namespace bv {
114116
if (m.is_bool(e))
115117
return m_eval.bval0(e) == m_eval.bval1(e);
116118
if (bv.is_bv(e))
117-
return 0 == m_eval.wval0(e).eq(m_eval.wval1(e));
119+
return m_eval.wval0(e).eq(m_eval.wval1(e));
118120
UNREACHABLE();
119121
return false;
120122
}

src/ast/sls/bv_sls_eval.cpp

+180-29
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ namespace bv {
9494
m_tmp2.push_back(0);
9595
m_tmp2.push_back(0);
9696
m_zero.push_back(0);
97+
m_one.push_back(0);
98+
m_one[0] = 1;
9799
}
98100
return r;
99101
}
@@ -207,10 +209,8 @@ namespace bv {
207209
for (unsigned i = a.nw; i < 2 * a.nw; ++i)
208210
if (m_tmp2[i] != 0)
209211
return true;
210-
for (unsigned i = a.bw; i < sizeof(digit_t) * 8 * a.nw; ++i)
211-
if (a.get(m_tmp2, i))
212-
return true;
213-
return false;
212+
return !a.has_overflow(m_tmp);
213+
return true;
214214
};
215215

216216
switch (e->get_decl_kind()) {
@@ -247,7 +247,7 @@ namespace bv {
247247
auto const& b = wval0(e->get_arg(1));
248248
digit_t c = 0;
249249
mpn.add(a.bits.data(), a.nw, b.bits.data(), b.nw, m_tmp.data(), a.nw, &c);
250-
return c != 0;
250+
return c != 0 || a.has_overflow(m_tmp);
251251
}
252252
case OP_BNEG_OVFL:
253253
case OP_BSADD_OVFL:
@@ -442,23 +442,110 @@ namespace bv {
442442
for (unsigned i = 0; i < a.bw; ++i)
443443
val.set(val.bits, i, i + sh < a.bw && b.get(b.bits, i + sh));
444444
if (sign)
445-
for (unsigned i = 0; i < sh; ++i)
446-
val.set(val.bits, a.bw - i, true);
445+
val.set_range(val.bits, 0, a.bw - sh, true);
447446
}
448447
break;
449448
}
450-
case OP_BSDIV:
451-
case OP_BSDIV_I:
452-
case OP_BSDIV0:
453-
case OP_BUDIV:
454-
case OP_BUDIV_I:
455-
case OP_BUDIV0:
449+
case OP_SIGN_EXT: {
450+
auto& a = wval0(e->get_arg(0));
451+
a.set(val.bits);
452+
bool sign = a.get(a.bits, a.bw - 1);
453+
val.set_range(val.bits, a.bw, val.bw, sign);
454+
break;
455+
}
456+
case OP_ZERO_EXT: {
457+
auto& a = wval0(e->get_arg(0));
458+
a.set(val.bits);
459+
val.set_range(val.bits, a.bw, val.bw, false);
460+
break;
461+
}
456462
case OP_BUREM:
457463
case OP_BUREM_I:
458-
case OP_BUREM0:
464+
case OP_BUREM0: {
465+
auto& a = wval0(e->get_arg(0));
466+
auto& b = wval0(e->get_arg(1));
467+
468+
if (b.is_zero())
469+
val.set(a.bits);
470+
else {
471+
mpn.div(a.bits.data(), a.nw,
472+
b.bits.data(), b.nw,
473+
m_tmp.data(), // quotient
474+
m_tmp2.data()); // remainder
475+
val.set(m_tmp2);
476+
}
477+
break;
478+
}
459479
case OP_BSMOD:
460480
case OP_BSMOD_I:
461-
case OP_BSMOD0:
481+
case OP_BSMOD0: {
482+
// u = mod(x,y)
483+
// u = 0 -> 0
484+
// y = 0 -> x
485+
// x < 0, y < 0 -> -u
486+
// x < 0, y >= 0 -> y - u
487+
// x >= 0, y < 0 -> y + u
488+
// x >= 0, y >= 0 -> u
489+
auto& a = wval0(e->get_arg(0));
490+
auto& b = wval0(e->get_arg(1));
491+
if (b.is_zero())
492+
val.set(a.bits);
493+
else {
494+
digit_t c;
495+
mpn.div(a.bits.data(), a.nw,
496+
b.bits.data(), b.nw,
497+
m_tmp.data(), // quotient
498+
m_tmp2.data()); // remainder
499+
if (val.is_zero(m_tmp2))
500+
val.set(m_tmp2);
501+
else if (a.sign() && b.sign())
502+
mpn.sub(m_zero.data(), a.nw, m_tmp2.data(), a.nw, m_tmp.data(), &c),
503+
val.set(m_tmp);
504+
else if (a.sign())
505+
mpn.sub(b.bits.data(), a.nw, m_tmp2.data(), a.nw, m_tmp.data(), &c),
506+
val.set(m_tmp);
507+
else if (b.sign())
508+
mpn.add(b.bits.data(), a.nw, m_tmp2.data(), a.nw, m_tmp.data(), a.nw, &c),
509+
val.set(m_tmp);
510+
else
511+
val.set(m_tmp2);
512+
}
513+
break;
514+
}
515+
case OP_BUDIV:
516+
case OP_BUDIV_I:
517+
case OP_BUDIV0: {
518+
// x div 0 = -1
519+
auto& a = wval0(e->get_arg(0));
520+
auto& b = wval0(e->get_arg(1));
521+
if (b.is_zero()) {
522+
val.set(m_zero);
523+
for (unsigned i = 0; i < a.nw; ++i)
524+
val.bits[i] = ~val.bits[i];
525+
}
526+
else {
527+
mpn.div(a.bits.data(), a.nw,
528+
b.bits.data(), b.nw,
529+
m_tmp.data(), // quotient
530+
m_tmp2.data()); // remainder
531+
val.set(m_tmp);
532+
}
533+
break;
534+
}
535+
536+
case OP_BSDIV:
537+
case OP_BSDIV_I:
538+
case OP_BSDIV0:
539+
// d = udiv(abs(x), abs(y))
540+
// y = 0, x > 0 -> 1
541+
// y = 0, x <= 0 -> -1
542+
// x = 0, y != 0 -> 0
543+
// x > 0, y < 0 -> -d
544+
// x < 0, y > 0 -> -d
545+
// x > 0, y > 0 -> d
546+
// x < 0, y < 0 -> d
547+
548+
462549
case OP_BREDAND:
463550
case OP_BREDOR:
464551
case OP_BXNOR:
@@ -595,10 +682,18 @@ namespace bv {
595682
else
596683
return try_repair_sle(!bval0(e), wval0(e, i), wval0(e, 1 - i));
597684
case OP_BASHR:
685+
return try_repair_ashr(wval0(e), wval0(e, 0), wval0(e, 1), i);
598686
case OP_BLSHR:
687+
return try_repair_lshr(wval0(e), wval0(e, 0), wval0(e, 1), i);
599688
case OP_BSHL:
689+
return try_repair_shl(wval0(e), wval0(e, 0), wval0(e, 1), i);
690+
case OP_BIT2BOOL: {
691+
unsigned idx;
692+
expr* arg;
693+
VERIFY(bv.is_bit2bool(e, arg, idx));
694+
return try_repair_bit2bool(wval0(e, 0), idx);
695+
}
600696
case OP_BCOMP:
601-
case OP_BIT2BOOL:
602697
case OP_BNAND:
603698
case OP_BREDAND:
604699
case OP_BREDOR:
@@ -751,15 +846,20 @@ namespace bv {
751846
* 8*e = a*(2b), then a = 4e*b^-1
752847
*/
753848
bool sls_eval::try_repair_mul(bvval const& e, bvval& a, bvval const& b) {
754-
unsigned parity_e = e.parity(e.bits);
755-
unsigned parity_b = b.parity(b.bits);
756-
if (parity_e < parity_b)
849+
if (b.is_zero()) {
850+
if (a.is_zero()) {
851+
a.set(m_tmp, 1);
852+
return a.try_set(m_tmp);
853+
}
757854
return false;
855+
}
758856
rational ne, nb;
759857
e.get_value(e.bits, ne);
760858
b.get_value(b.bits, nb);
859+
unsigned parity_e = e.parity(e.bits);
860+
unsigned parity_b = b.parity(b.bits);
761861
if (parity_b > 0)
762-
ne /= rational::power_of_two(parity_b);
862+
ne /= rational::power_of_two(std::min(parity_b, parity_e));
763863
auto inv_b = nb.pseudo_inverse(b.bw);
764864
rational na = mod(inv_b * ne, rational::power_of_two(a.bw));
765865
a.set_value(m_tmp, na);
@@ -774,18 +874,16 @@ namespace bv {
774874

775875
bool sls_eval::try_repair_bneg(bvval const& e, bvval& a) {
776876
digit_t c;
777-
mpn.sub(m_zero.data(), e.nw, e.bits.data(), e.nw, m_tmp.data(), &c);
877+
mpn.sub(m_zero.data(), e.nw, e.bits.data(), e.nw, m_tmp.data(), &c);
778878
return a.try_set(m_tmp);
779879
}
780880

781881
bool sls_eval::try_repair_ule(bool e, bvval& a, bvval const& b) {
782882
if (e)
783883
return a.try_set(b.bits);
784884
else {
785-
digit_t c;
786-
a.set(m_zero, 0, true);
787-
mpn.add(b.bits.data(), a.nw, m_zero.data(), a.nw, &c, a.nw, m_tmp.data());
788-
a.set(m_zero, 0, false);
885+
digit_t c;
886+
mpn.add(b.bits.data(), a.nw, m_one.data(), a.nw, &c, a.nw, m_tmp.data());
789887
return a.try_set(m_tmp);
790888
}
791889
}
@@ -795,18 +893,71 @@ namespace bv {
795893
return a.try_set(b.bits);
796894
else {
797895
digit_t c;
798-
a.set(m_zero, 0, true);
799-
mpn.sub(b.bits.data(), a.nw, m_zero.data(), a.nw, m_tmp.data(), &c);
800-
a.set(m_zero, 0, false);
896+
mpn.sub(b.bits.data(), a.nw, m_one.data(), a.nw, m_tmp.data(), &c);
801897
return a.try_set(m_tmp);
802898
}
803899
}
804900

805901
bool sls_eval::try_repair_sle(bool e, bvval& a, bvval const& b) {
806-
return false;
902+
return try_repair_ule(e, a, b);
807903
}
808904

809905
bool sls_eval::try_repair_sge(bool e, bvval& a, bvval const& b) {
906+
return try_repair_uge(e, a, b);
907+
}
908+
909+
bool sls_eval::try_repair_bit2bool(bvval& a, unsigned idx) {
910+
for (unsigned i = 0; i < a.nw; ++i)
911+
m_tmp[i] = a.bits[i];
912+
a.set(m_tmp, idx, !a.get(a.bits, idx));
913+
return a.try_set(m_tmp);
914+
}
915+
916+
bool sls_eval::try_repair_shl(bvval const& e, bvval& a, bvval& b, unsigned i) {
917+
if (i == 0) {
918+
unsigned sh = b.to_nat(b.bits, b.bw);
919+
if (sh == 0)
920+
return a.try_set(e.bits);
921+
else if (sh >= b.bw) {
922+
return false;
923+
}
924+
else {
925+
//
926+
// e = a << sh
927+
// set bw - sh low order bits to bw - sh high-order of e.
928+
// a[bw - sh - 1: 0] = e[bw - 1: sh]
929+
// a[bw - 1: bw - sh] = unchanged
930+
//
931+
for (unsigned i = 0; i < e.bw - sh; ++i)
932+
e.set(m_tmp, i, e.get(e.bits, sh + i));
933+
for (unsigned i = e.bw - sh; i < e.bw; ++i)
934+
e.set(m_tmp, i, e.get(a.bits, i));
935+
return a.try_set(m_tmp);
936+
}
937+
}
938+
else {
939+
SASSERT(i == 1);
940+
}
941+
return false;
942+
}
943+
944+
bool sls_eval::try_repair_ashr(bvval const& e, bvval & a, bvval& b, unsigned i) {
945+
if (i == 0) {
946+
947+
}
948+
else {
949+
950+
}
951+
return false;
952+
}
953+
954+
bool sls_eval::try_repair_lshr(bvval const& e, bvval& a, bvval& b, unsigned i) {
955+
if (i == 0) {
956+
957+
}
958+
else {
959+
960+
}
810961
return false;
811962
}
812963

src/ast/sls/bv_sls_eval.h

+6-2
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@ namespace bv {
3030
ast_manager& m;
3131
bv_util bv;
3232
sls_fixed m_fix;
33-
mpn_manager mpn;
33+
mutable mpn_manager mpn;
3434
ptr_vector<expr> m_todo;
3535
random_gen m_rand;
3636

3737
scoped_ptr_vector<sls_valuation> m_values0, m_values1; // expr-id -> bv valuation
3838
bool_vector m_eval; // expr-id -> boolean valuation
3939
bool_vector m_fixed; // expr-id -> is Boolean fixed
4040

41-
mutable svector<digit_t> m_tmp, m_tmp2, m_zero;
41+
mutable svector<digit_t> m_tmp, m_tmp2, m_zero, m_one;
4242

4343
using bvval = sls_valuation;
4444

@@ -78,6 +78,10 @@ namespace bv {
7878
bool try_repair_uge(bool e, bvval& a, bvval const& b);
7979
bool try_repair_sle(bool e, bvval& a, bvval const& b);
8080
bool try_repair_sge(bool e, bvval& a, bvval const& b);
81+
bool try_repair_shl(bvval const& e, bvval& a, bvval& b, unsigned i);
82+
bool try_repair_ashr(bvval const& e, bvval& a, bvval& b, unsigned i);
83+
bool try_repair_lshr(bvval const& e, bvval& a, bvval& b, unsigned i);
84+
bool try_repair_bit2bool(bvval& a, unsigned idx);
8185

8286
sls_valuation& wval0(app* e, unsigned i) { return wval0(e->get_arg(i)); }
8387

src/ast/sls/sls_valuation.h

+29
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,23 @@ namespace bv {
5454
return 0 > memcmp(a.data(), b.data(), num_bytes());
5555
}
5656

57+
bool is_zero() const { return is_zero(bits); }
58+
bool is_zero(svector<digit_t> const& a) const {
59+
for (unsigned i = 0; i < nw; ++i)
60+
if (a[i] != 0)
61+
return false;
62+
return true;
63+
}
64+
65+
bool sign() const { return get(bits, bw - 1); }
66+
67+
bool has_overflow(svector<digit_t> const& bits) const {
68+
for (unsigned i = bw; i < nw * sizeof(digit_t) * 8; ++i)
69+
if (get(bits, i))
70+
return true;
71+
return false;
72+
}
73+
5774
unsigned parity(svector<digit_t> const& bits) const {
5875
unsigned i = 0;
5976
for (; i < bw && !get(bits, i); ++i);
@@ -73,16 +90,28 @@ namespace bv {
7390
clear_overflow_bits(bits);
7491
}
7592

93+
7694
void set_fixed(svector<digit_t> const& src) {
7795
for (unsigned i = nw; i-- > 0; )
7896
fixed[i] = src[i];
7997
}
8098

99+
void set_range(svector<digit_t>& dst, unsigned lo, unsigned hi, bool b) {
100+
for (unsigned i = lo; i < hi; ++i)
101+
set(dst, i, b);
102+
}
103+
81104
void set(svector<digit_t>& d, unsigned bit_idx, bool val) const {
82105
auto _val = static_cast<digit_t>(0 - static_cast<digit_t>(val));
83106
get_bit_word(d, bit_idx) ^= (_val ^ get_bit_word(d, bit_idx)) & get_pos_mask(bit_idx);
84107
}
85108

109+
void set(svector<digit_t>& dst, unsigned v) const {
110+
dst[0] = v;
111+
for (unsigned i = 1; i < nw; ++i)
112+
dst[i] = 0;
113+
}
114+
86115
bool get(svector<digit_t> const& d, unsigned bit_idx) const {
87116
return (get_bit_word(d, bit_idx) & get_pos_mask(bit_idx)) != 0;
88117
}

0 commit comments

Comments
 (0)