@@ -161,20 +161,27 @@ namespace euf {
161
161
void bv_plugin::propagate_values (enode* x) {
162
162
if (!is_value (x))
163
163
return ;
164
-
164
+
165
+ auto val_x = get_value (x);
165
166
enode* a, * b;
166
- for (enode* p : enode_parents (x))
167
- if (is_concat (p, a, b) && is_value (a) && is_value (b) && !is_value (p))
167
+ unsigned lo, hi;
168
+ for (enode* p : enode_parents (x)) {
169
+ if (is_concat (p, a, b) && is_value (a) && is_value (b))
168
170
push_merge (mk_concat (a->get_interpreted (), b->get_interpreted ()), mk_value_concat (a, b));
169
-
171
+
172
+ if (is_extract (p, lo, hi)) {
173
+ auto val_p = mod2k (machine_div2k (val_x, lo), hi - lo + 1 );
174
+ auto ix = x->get_interpreted ();
175
+ auto ex = mk (bv.mk_extract (hi, lo, ix->get_expr ()), 1 , &ix);
176
+ push_merge (ex, mk_value (val_p, width (p)));
177
+ }
178
+ }
179
+
170
180
for (enode* sib : enode_class (x)) {
171
181
if (is_concat (sib, a, b)) {
172
- if (!is_value (a) || !is_value (b)) {
173
- auto val = get_value (x);
174
- auto val_a = machine_div2k (val, width (b));
175
- auto val_b = mod2k (val, width (b));
176
- push_merge (mk_concat (mk_value (val_a, width (a)), mk_value (val_b, width (b))), x->get_interpreted ());
177
- }
182
+ auto val_a = machine_div2k (val_x, width (b));
183
+ auto val_b = mod2k (val_x, width (b));
184
+ push_merge (mk_concat (mk_value (val_a, width (a)), mk_value (val_b, width (b))), x->get_interpreted ());
178
185
}
179
186
}
180
187
}
@@ -198,7 +205,9 @@ namespace euf {
198
205
enode* arg_r = arg->get_root ();
199
206
enode* n_r = n->get_root ();
200
207
208
+ m_ensure_concat.reset ();
201
209
auto ensure_concat = [&](unsigned lo, unsigned mid, unsigned hi) {
210
+ // verbose_stream() << lo << " " << mid << " " << hi << "\n";
202
211
TRACE (" bv" , tout << " ensure-concat " << lo << " " << mid << " " << hi << " \n " );
203
212
unsigned lo_, hi_;
204
213
for (enode* p1 : enode_parents (n))
@@ -212,14 +221,14 @@ namespace euf {
212
221
TRACE (" bv" , tout << " propagate-above " << g.bpp (b) << " \n " );
213
222
for (enode* sib : enode_class (b))
214
223
if (is_extract (sib, lo2, hi2) && sib->get_arg (0 )->get_root () == arg_r && hi1 + 1 == lo2)
215
- ensure_concat ( lo1, hi1, hi2);
224
+ m_ensure_concat. push_back ({ lo1, hi1, hi2} );
216
225
};
217
226
218
227
auto propagate_below = [&](enode* a) {
219
228
TRACE (" bv" , tout << " propagate-below " << g.bpp (a) << " \n " );
220
229
for (enode* sib : enode_class (a))
221
230
if (is_extract (sib, lo2, hi2) && sib->get_arg (0 )->get_root () == arg_r && hi2 + 1 == lo1)
222
- ensure_concat ( lo2, hi2, hi1);
231
+ m_ensure_concat. push_back ({ lo2, hi2, hi1} );
223
232
};
224
233
225
234
for (enode* p : enode_parents (n)) {
@@ -230,6 +239,10 @@ namespace euf {
230
239
propagate_above (a);
231
240
}
232
241
}
242
+
243
+ for (auto [lo, mid, hi] : m_ensure_concat)
244
+ ensure_concat (lo, mid, hi);
245
+
233
246
}
234
247
235
248
class bv_plugin ::undo_split : public trail {
@@ -432,13 +445,14 @@ namespace euf {
432
445
delta += width (arg);
433
446
}
434
447
}
435
- }
436
- for ( auto p : euf::enode_parents (n-> get_root () )) {
437
- if (bv. is_extract (p-> get_expr (), lo, hi, e)) {
438
- SASSERT (g. find (e)-> get_root () == n-> get_root () );
439
- m_todo. push_back ({ p, offset + lo });
448
+ for ( auto p : euf::enode_parents (sib)) {
449
+ if (bv. is_extract (p-> get_expr (), lo, hi, e )) {
450
+ SASSERT (g. find (e)-> get_root () == n-> get_root ());
451
+ m_todo. push_back ({ p, offset + lo } );
452
+ }
440
453
}
441
454
}
455
+
442
456
}
443
457
clear_offsets ();
444
458
}
@@ -462,17 +476,17 @@ namespace euf {
462
476
auto child = g.find (e);
463
477
m_todo.push_back ({ child, offset + lo });
464
478
}
465
- }
466
- for ( auto p : euf::enode_parents (n-> get_root ())) {
467
- if (bv. is_concat (p-> get_expr ())) {
468
- unsigned delta = 0 ;
469
- for ( unsigned j = p->num_args (); j-- > 0 ; ) {
470
- auto arg = p-> get_arg (j);
471
- if (arg-> get_root () == n-> get_root ())
472
- m_todo. push_back ({ p, offset + delta } );
473
- delta += width (arg);
479
+ for ( auto p : euf::enode_parents (sib)) {
480
+ if (bv. is_concat (p-> get_expr ())) {
481
+ unsigned delta = 0 ;
482
+ for ( unsigned j = p-> num_args (); j-- > 0 ; ) {
483
+ auto arg = p->get_arg (j);
484
+ if ( arg-> get_root () == n-> get_root ())
485
+ m_todo. push_back ({ p, offset + delta });
486
+ delta += width (arg );
487
+ }
474
488
}
475
- }
489
+ }
476
490
}
477
491
}
478
492
clear_offsets ();
@@ -511,6 +525,9 @@ namespace euf {
511
525
m_offsets.reserve (n->get_root_id () + 1 );
512
526
m_offsets[n->get_root_id ()].reset ();
513
527
}
528
+ for (auto const & off : m_offsets) {
529
+ SASSERT (off.empty ());
530
+ }
514
531
m_jtodo.reset ();
515
532
return ;
516
533
}
@@ -521,20 +538,27 @@ namespace euf {
521
538
just.push_back ({ n, sib, j });
522
539
for (unsigned j = sib->num_args (); j-- > 0 ; ) {
523
540
auto arg = sib->get_arg (j);
524
- m_jtodo.push_back ({ arg, offset + delta, j2 });
541
+ m_jtodo.push_back ({ arg, offs + delta, j2 });
525
542
delta += width (arg);
526
543
}
527
544
}
528
- }
529
- for ( auto p : euf::enode_parents (n-> get_root () )) {
530
- if (bv. is_extract (p-> get_expr (), lo, hi, e)) {
531
- SASSERT (g. find (e)-> get_root () == n-> get_root () );
532
- unsigned j2 = just.size ( );
533
- just .push_back ({ g. find (e), n, j });
534
- m_jtodo. push_back ({ p, offset + lo, j2});
545
+ for ( auto p : euf::enode_parents (sib)) {
546
+ if (bv. is_extract (p-> get_expr (), lo, hi, e )) {
547
+ SASSERT (g. find (e)-> get_root () == n-> get_root ());
548
+ unsigned j2 = just. size ( );
549
+ just.push_back ({ g. find (e), n, j } );
550
+ m_jtodo .push_back ({ p, offs + lo, j2 });
551
+ }
535
552
}
536
553
}
554
+
537
555
}
556
+ IF_VERBOSE (0 ,
557
+ g.display (verbose_stream ());
558
+ verbose_stream () << g.bpp (a) << " offset " << offset << " " << g.bpp (b) << " \n " ;
559
+ for (auto const & [n, offset, j] : m_jtodo)
560
+ verbose_stream () << g.bpp (n) << " offset " << offset << " " << g.bpp (n->get_root ()) << " \n " ;
561
+ );
538
562
UNREACHABLE ();
539
563
}
540
564
0 commit comments