3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-12 20:18:18 +00:00

only case expand for cases that contain defs. fixes #2601

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2019-10-01 18:41:11 -07:00
parent 88f0e4a64c
commit 6616b6a366
2 changed files with 25 additions and 10 deletions

View file

@ -64,17 +64,30 @@ namespace recfun {
m_decl = m.mk_func_decl(s, arity, domain, range, info); m_decl = m.mk_func_decl(s, arity, domain, range, info);
} }
bool def::contains_def(util& u, expr * e) {
struct def_find_p : public i_expr_pred {
util& u;
def_find_p(util& u): u(u) {}
bool operator()(expr* a) override { return is_app(a) && u.is_defined(to_app(a)->get_decl()); }
};
def_find_p p(u);
check_pred cp(p, m, false);
return cp(e);
}
// does `e` contain any `ite` construct? // does `e` contain any `ite` construct?
bool def::contains_ite(expr * e) { bool def::contains_ite(util& u, expr * e) {
struct ite_find_p : public i_expr_pred { struct ite_find_p : public i_expr_pred {
ast_manager & m; ast_manager & m;
ite_find_p(ast_manager & m) : m(m) {} def& d;
bool operator()(expr * e) override { return m.is_ite(e); } util& u;
ite_find_p(ast_manager & m, def& d, util& u) : m(m), d(d), u(u) {}
bool operator()(expr * e) override { return m.is_ite(e) && d.contains_def(u, e); }
}; };
// ignore ites under quantifiers. // ignore ites under quantifiers.
// this is redundant as the code // this is redundant as the code
// that unfolds ites uses quantifier-free portion. // that unfolds ites uses quantifier-free portion.
ite_find_p p(m); ite_find_p p(m, *this, u);
check_pred cp(p, m, false); check_pred cp(p, m, false);
return cp(e); return cp(e);
} }
@ -189,7 +202,8 @@ namespace recfun {
// Compute a set of cases, given the RHS // Compute a set of cases, given the RHS
void def::compute_cases(replace& subst, void def::compute_cases(util& u,
replace& subst,
is_immediate_pred & is_i, is_immediate_pred & is_i,
unsigned n_vars, var *const * vars, expr* rhs) unsigned n_vars, var *const * vars, expr* rhs)
{ {
@ -209,7 +223,7 @@ namespace recfun {
expr_ref_vector conditions(m); expr_ref_vector conditions(m);
// is the function a macro (unconditional body)? // is the function a macro (unconditional body)?
if (n_vars == 0 || !contains_ite(rhs)) { if (n_vars == 0 || !contains_ite(u, rhs)) {
// constant function or trivial control flow, only one (dummy) case // constant function or trivial control flow, only one (dummy) case
add_case(name, 0, conditions, rhs); add_case(name, 0, conditions, rhs);
return; return;
@ -248,7 +262,7 @@ namespace recfun {
else if (is_app(e)) { else if (is_app(e)) {
// explore arguments // explore arguments
for (expr * arg : *to_app(e)) { for (expr * arg : *to_app(e)) {
if (contains_ite(arg)) { if (contains_ite(u, arg)) {
stack.push_back(arg); stack.push_back(arg);
} }
} }
@ -361,7 +375,7 @@ namespace recfun {
SASSERT(n_vars == d->get_arity()); SASSERT(n_vars == d->get_arity());
is_imm_pred is_i(*u); is_imm_pred is_i(*u);
d->compute_cases(r, is_i, n_vars, vars, rhs); d->compute_cases(*u, r, is_i, n_vars, vars, rhs);
} }
namespace decl { namespace decl {

View file

@ -111,10 +111,11 @@ namespace recfun {
def(ast_manager &m, family_id fid, symbol const & s, unsigned arity, sort *const * domain, sort* range, bool is_generated); def(ast_manager &m, family_id fid, symbol const & s, unsigned arity, sort *const * domain, sort* range, bool is_generated);
// compute cases for a function, given its RHS (possibly containing `ite`). // compute cases for a function, given its RHS (possibly containing `ite`).
void compute_cases(replace& subst, is_immediate_pred &, void compute_cases(util& u, replace& subst, is_immediate_pred &,
unsigned n_vars, var *const * vars, expr* rhs); unsigned n_vars, var *const * vars, expr* rhs);
void add_case(std::string & name, unsigned case_index, expr_ref_vector const& conditions, expr* rhs, bool is_imm = false); void add_case(std::string & name, unsigned case_index, expr_ref_vector const& conditions, expr* rhs, bool is_imm = false);
bool contains_ite(expr* e); // expression contains a test? bool contains_ite(util& u, expr* e); // expression contains a test?
bool contains_def(util& u, expr* e); // expression contains a def
public: public:
symbol const & get_name() const { return m_name; } symbol const & get_name() const { return m_name; }
vars const & get_vars() const { return m_vars; } vars const & get_vars() const { return m_vars; }