/*++ Copyright (c) 2006 Microsoft Corporation Module Name: smt_almost_cg_table.cpp Abstract: Author: Leonardo de Moura (leonardo) 2009-03-06. Revision History: --*/ #include"smt_almost_cg_table.h" namespace smt { inline unsigned almost_cg_table::cg_hash::arg_hash(enode * n, unsigned idx) const { enode * arg = n->get_arg(idx)->get_root(); if (arg == m_r1 || arg == m_r2) return 17; return arg->hash(); } unsigned almost_cg_table::cg_hash::operator()(enode * n) const { unsigned num_args = n->get_num_args(); unsigned kind_hash = n->get_decl_id(); if (num_args == 1) return kind_hash; unsigned a = 0x9e3779b9; unsigned b = 0x9e3779b9; unsigned c = 11; switch (num_args) { case 2: a += kind_hash; b += arg_hash(n, 0); c += arg_hash(n, 1); mix(a, b, c); return c; case 3: a += kind_hash; b += arg_hash(n, 0); c += arg_hash(n, 1); mix(a, b, c); c += arg_hash(n, 1); mix(a, b, c); return c; default: while (num_args >= 3) { num_args--; a += arg_hash(n, num_args); num_args--; b += arg_hash(n, num_args); num_args--; c += arg_hash(n, num_args); mix(a, b, c); } a += kind_hash; switch (num_args) { case 2: b += arg_hash(n, 1); __fallthrough; case 1: c += arg_hash(n, 0); } mix(a, b, c); return c; } } bool almost_cg_table::cg_eq::operator()(enode * n1, enode * n2) const { if (n1->get_owner()->get_decl() != n2->get_owner()->get_decl()) return false; unsigned num_args = n1->get_num_args(); if (num_args != n2->get_num_args()) return false; for (unsigned j = 0; j < num_args; j++) { enode * arg1 = n1->get_arg(j)->get_root(); enode * arg2 = n2->get_arg(j)->get_root(); if (arg1 == arg2) continue; if ((arg1 == m_r1 || arg1 == m_r2) && (arg2 == m_r1 || arg2 == m_r2)) continue; return false; } return true; } almost_cg_table::almost_cg_table(enode * r1, enode * r2): m_r1(r1), m_r2(r2), m_table(cg_hash(m_r1, m_r2), cg_eq(m_r1, m_r2)) { } void almost_cg_table::reset() { m_region.reset(); m_table.reset(); } void almost_cg_table::insert(enode * n) { table::entry * entry = m_table.find_core(n); if (entry == 0) { list * new_lst = new (m_region) list(n, 0); m_table.insert(n, new_lst); } else { list * new_lst = new (m_region) list(n, entry->get_data().m_value); entry->get_data().m_value = new_lst; } } list * almost_cg_table::find(enode * n) { list * result = 0; m_table.find(n, result); return result; } };