@@ -352,6 +352,140 @@ namespace euf {
352
352
push_merge (mk_concat (lo, hi), n);
353
353
}
354
354
355
+ void bv_plugin::sub_slices (enode* n, std::function<bool (enode*, unsigned )>& consumer) {
356
+ m_todo.push_back ({ n, 0 });
357
+ unsigned lo, hi;
358
+ expr* e;
359
+
360
+ for (unsigned i = 0 ; i < m_todo.size (); ++i) {
361
+ auto [n, offset] = m_todo[i];
362
+ m_offsets.reserve (n->get_root_id () + 1 );
363
+ auto & offsets = m_offsets[n->get_root_id ()];
364
+ if (offsets.contains (offset))
365
+ continue ;
366
+ offsets.push_back (offset);
367
+ if (!consumer (n, offset))
368
+ continue ;
369
+ for (auto sib : euf::enode_class (n)) {
370
+ if (bv.is_concat (sib->get_expr ())) {
371
+ unsigned delta = 0 ;
372
+ for (unsigned j = sib->num_args (); j-- > 0 ; ) {
373
+ auto arg = sib->get_arg (j);
374
+ m_todo.push_back ({ arg, offset + delta });
375
+ delta += width (arg);
376
+ }
377
+ }
378
+ }
379
+ for (auto p : euf::enode_parents (n->get_root ())) {
380
+ if (bv.is_extract (p->get_expr (), lo, hi, e)) {
381
+ SASSERT (g.find (e)->get_root () == n->get_root ());
382
+ m_todo.push_back ({ p, offset + lo });
383
+ }
384
+ }
385
+ }
386
+ clear_offsets ();
387
+ }
388
+
389
+ void bv_plugin::super_slices (enode* n, std::function<bool (enode*, unsigned )>& consumer) {
390
+ m_todo.push_back ({ n, 0 });
391
+ unsigned lo, hi;
392
+ expr* e;
393
+
394
+ for (unsigned i = 0 ; i < m_todo.size (); ++i) {
395
+ auto [n, offset] = m_todo[i];
396
+ m_offsets.reserve (n->get_root_id () + 1 );
397
+ auto & offsets = m_offsets[n->get_root_id ()];
398
+ if (offsets.contains (offset))
399
+ continue ;
400
+ offsets.push_back (offset);
401
+ if (!consumer (n, offset))
402
+ continue ;
403
+ for (auto sib : euf::enode_class (n)) {
404
+ if (bv.is_extract (sib->get_expr (), lo, hi, e)) {
405
+ auto child = g.find (e);
406
+ m_todo.push_back ({ child, offset + lo });
407
+ }
408
+ }
409
+ for (auto p : euf::enode_parents (n->get_root ())) {
410
+ if (bv.is_concat (p->get_expr ())) {
411
+ unsigned delta = 0 ;
412
+ for (unsigned j = p->num_args (); j-- > 0 ; ) {
413
+ auto arg = p->get_arg (j);
414
+ if (arg->get_root () == n->get_root ())
415
+ m_todo.push_back ({ p, offset + delta });
416
+ delta += width (arg);
417
+ }
418
+ }
419
+ }
420
+ }
421
+ clear_offsets ();
422
+ }
423
+
424
+ //
425
+ // Explain that a is a subslice of b at offset
426
+ // or that b is a subslice of a at offset
427
+ //
428
+ void bv_plugin::explain_slice (enode* a, unsigned offset, enode* b, std::function<void (enode*, enode*)>& consumer) {
429
+ if (width (a) < width (b))
430
+ std::swap (a, b);
431
+ SASSERT (width (a) >= width (b));
432
+ svector<std::tuple<enode*, enode*, unsigned >> just;
433
+ m_jtodo.push_back ({ a, 0 , UINT_MAX });
434
+ unsigned lo, hi;
435
+ expr* e;
436
+
437
+ for (unsigned i = 0 ; i < m_jtodo.size (); ++i) {
438
+ auto [n, offs, j] = m_jtodo[i];
439
+ m_offsets.reserve (n->get_root_id () + 1 );
440
+ auto & offsets = m_offsets[n->get_root_id ()];
441
+ if (offsets.contains (offs))
442
+ continue ;
443
+ offsets.push_back (offs);
444
+ if (n->get_root () == b->get_root () && offs == offset) {
445
+ while (j != UINT_MAX) {
446
+ auto [x, y, j2] = just[j];
447
+ consumer (x, y);
448
+ j = j2;
449
+ }
450
+ for (auto const & [n, offset, j] : m_jtodo) {
451
+ m_offsets.reserve (n->get_root_id () + 1 );
452
+ m_offsets[n->get_root_id ()].reset ();
453
+ }
454
+ m_jtodo.reset ();
455
+ return ;
456
+ }
457
+ for (auto sib : euf::enode_class (n)) {
458
+ if (bv.is_concat (sib->get_expr ())) {
459
+ unsigned delta = 0 ;
460
+ unsigned j2 = just.size ();
461
+ just.push_back ({ n, sib, j });
462
+ for (unsigned j = sib->num_args (); j-- > 0 ; ) {
463
+ auto arg = sib->get_arg (j);
464
+ m_jtodo.push_back ({ arg, offset + delta, j2 });
465
+ delta += width (arg);
466
+ }
467
+ }
468
+ }
469
+ for (auto p : euf::enode_parents (n->get_root ())) {
470
+ if (bv.is_extract (p->get_expr (), lo, hi, e)) {
471
+ SASSERT (g.find (e)->get_root () == n->get_root ());
472
+ unsigned j2 = just.size ();
473
+ just.push_back ({ g.find (e), n, j});
474
+ m_jtodo.push_back ({ p, offset + lo, j2});
475
+ }
476
+ }
477
+ }
478
+ UNREACHABLE ();
479
+ }
480
+
481
+ void bv_plugin::clear_offsets () {
482
+ for (auto const & [n, offset] : m_todo) {
483
+ m_offsets.reserve (n->get_root_id () + 1 );
484
+ m_offsets[n->get_root_id ()].reset ();
485
+ }
486
+ m_todo.reset ();
487
+ }
488
+
355
489
std::ostream& bv_plugin::display (std::ostream& out) const {
356
490
out << " bv\n " ;
357
491
for (auto const & i : m_info)
0 commit comments