Skip to content

Commit ad07e0e

Browse files
add sub and super-slice functionality directory to euf-bv-plugin
1 parent cd331b8 commit ad07e0e

File tree

2 files changed

+147
-0
lines changed

2 files changed

+147
-0
lines changed

src/ast/euf/euf_bv_plugin.cpp

+134
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,140 @@ namespace euf {
352352
push_merge(mk_concat(lo, hi), n);
353353
}
354354

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+
355489
std::ostream& bv_plugin::display(std::ostream& out) const {
356490
out << "bv\n";
357491
for (auto const& i : m_info)

src/ast/euf/euf_bv_plugin.h

+13
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ namespace euf {
4141
bv_util bv;
4242
slice_info_vector m_info; // indexed by enode::get_id()
4343

44+
45+
4446
enode_vector m_xs, m_ys;
4547

4648
bool is_concat(enode* n) const { return bv.is_concat(n->get_expr()); }
@@ -74,6 +76,11 @@ namespace euf {
7476
void propagate_extract(enode* n);
7577
void propagate_values(enode* n);
7678

79+
vector<unsigned_vector> m_offsets;
80+
svector<std::pair<enode*, unsigned>> m_todo;
81+
svector<std::tuple<enode*, unsigned, unsigned>> m_jtodo;
82+
void clear_offsets();
83+
7784
enode_vector m_undo_split;
7885
void push_undo_split(enode* n);
7986

@@ -95,6 +102,12 @@ namespace euf {
95102
void undo() override;
96103

97104
std::ostream& display(std::ostream& out) const override;
105+
106+
void sub_slices(enode* n, std::function<bool(enode*, unsigned)>& consumer);
107+
108+
void super_slices(enode* n, std::function<bool(enode*, unsigned)>& consumer);
109+
110+
void explain_slice(enode* a, unsigned offset, enode* b, std::function<void(enode*, enode*)>& consumer);
98111

99112
};
100113
}

0 commit comments

Comments
 (0)