expr * reuse(set & s, func_decl * f, expr * arg1, expr * arg2) { if (s.contains(expr_pair(arg1, arg2))) return m().mk_app(f, arg1, arg2); if (s.contains(expr_pair(arg2, arg1))) return m().mk_app(f, arg2, arg1); return 0; }
bool matcher::operator()(expr * e1, expr * e2, substitution & s) { reset(); m_subst = &s; m_todo.push_back(expr_pair(e1, e2)); while (!m_todo.empty()) { expr_pair const & p = m_todo.back(); // if (m_cache.contains(p)) { // m_todo.pop_back(); // continue; // } if (is_var(p.first)) { expr_offset r; if (m_subst->find(to_var(p.first), 0, r)) { if (r.get_expr() != p.second) return false; } else { m_subst->insert(to_var(p.first), 0, expr_offset(p.second, 1)); } m_todo.pop_back(); continue; } if (is_var(p.second)) return false; if (!is_app(p.first)) return false; if (!is_app(p.second)) return false; app * n1 = to_app(p.first); app * n2 = to_app(p.second); if (n1->get_decl() != n2->get_decl()) return false; unsigned num_args1 = n1->get_num_args(); if (num_args1 != n2->get_num_args()) return false; m_todo.pop_back(); if (num_args1 == 0) continue; // m_cache.insert(p); unsigned j = num_args1; while (j > 0) { --j; m_todo.push_back(expr_pair(n1->get_arg(j), n2->get_arg(j))); } } return true; }
br_status reduce_ac_app(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { set & s = f2set(f); if (num_args == 2) { if (!m_util.is_numeral(args[0]) && !m_util.is_numeral(args[1])) s.insert(expr_pair(args[0], args[1])); return BR_FAILED; } ptr_buffer<expr, 128> _args; bool first = false; expr * num = 0; for (unsigned i = 0; i < num_args; i++) { expr * arg = args[i]; if (num == 0 && m_util.is_numeral(arg)) { if (i == 0) first = true; num = arg; } else { _args.push_back(arg); } } num_args = _args.size(); // std::sort(_args.begin(), _args.end(), ref_count_lt()); // std::sort(_args.begin(), _args.end(), ast_to_lt()); try_to_reuse: if (num_args > 1 && num_args < m_max_args) { for (unsigned i = 0; i < num_args - 1; i++) { for (unsigned j = i + 1; j < num_args; j++) { expr * r = reuse(s, f, _args[i], _args[j]); if (r != 0) { TRACE("bv_sharing_detail", tout << "reusing args: " << i << " " << j << "\n";); _args[i] = r; SASSERT(num_args > 1); for (unsigned w = j; w < num_args - 1; w++) { _args[w] = _args[w+1]; } num_args--; goto try_to_reuse; } } }