mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 09:05:31 +00:00
checkpoint
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
8a4f6d5719
commit
1ea606092c
50 changed files with 279 additions and 211 deletions
128
src/ast/rewriter/bit_blaster/bit_blaster.cpp
Normal file
128
src/ast/rewriter/bit_blaster/bit_blaster.cpp
Normal file
|
@ -0,0 +1,128 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
bit_blaster.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-06-05.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"bit_blaster.h"
|
||||
#include"bit_blaster_tpl_def.h"
|
||||
#include"ast_pp.h"
|
||||
#include"bv_decl_plugin.h"
|
||||
|
||||
bit_blaster_cfg::bit_blaster_cfg(bv_util & u, bit_blaster_params const & p, basic_simplifier_plugin & _s):
|
||||
m_util(u),
|
||||
m_params(p),
|
||||
s(_s) {
|
||||
}
|
||||
|
||||
static void sort_args(expr * & l1, expr * & l2, expr * & l3) {
|
||||
expr * args[3] = {l1, l2, l3};
|
||||
// ast_lt_proc is based on the AST ids. So, it is a total order on AST nodes.
|
||||
// No need for stable_sort
|
||||
std::sort(args, args+3, ast_lt_proc());
|
||||
l1 = args[0]; l2 = args[1]; l3 = args[2];
|
||||
}
|
||||
|
||||
void bit_blaster_cfg::mk_xor3(expr * l1, expr * l2, expr * l3, expr_ref & r) {
|
||||
TRACE("xor3", tout << "#" << l1->get_id() << " #" << l2->get_id() << " #" << l3->get_id(););
|
||||
sort_args(l1, l2, l3);
|
||||
TRACE("xor3_sorted", tout << "#" << l1->get_id() << " #" << l2->get_id() << " #" << l3->get_id(););
|
||||
if (m_params.m_bb_ext_gates) {
|
||||
if (l1 == l2)
|
||||
r = l3;
|
||||
else if (l1 == l3)
|
||||
r = l2;
|
||||
else if (l2 == l3)
|
||||
r = l1;
|
||||
else if (m().is_complement(l1, l2))
|
||||
s.mk_not(l3, r);
|
||||
else if (m().is_complement(l1, l3))
|
||||
s.mk_not(l2, r);
|
||||
else if (m().is_complement(l2, l3))
|
||||
s.mk_not(l1, r);
|
||||
else if (m().is_true(l1))
|
||||
s.mk_iff(l2, l3, r);
|
||||
else if (m().is_false(l1))
|
||||
s.mk_xor(l2, l3, r);
|
||||
else if (m().is_true(l2))
|
||||
s.mk_iff(l1, l3, r);
|
||||
else if (m().is_false(l2))
|
||||
s.mk_xor(l1, l3, r);
|
||||
else if (m().is_true(l3))
|
||||
s.mk_iff(l1, l2, r);
|
||||
else if (m().is_false(l3))
|
||||
s.mk_xor(l1, l2, r);
|
||||
else
|
||||
r = m().mk_app(m_util.get_family_id(), OP_XOR3, l1, l2, l3);
|
||||
}
|
||||
else {
|
||||
expr_ref t(m());
|
||||
s.mk_xor(l1, l2, t);
|
||||
s.mk_xor(t, l3, r);
|
||||
}
|
||||
}
|
||||
|
||||
void bit_blaster_cfg::mk_carry(expr * l1, expr * l2, expr * l3, expr_ref & r) {
|
||||
TRACE("carry", tout << "#" << l1->get_id() << " #" << l2->get_id() << " #" << l3->get_id(););
|
||||
sort_args(l1, l2, l3);
|
||||
TRACE("carry_sorted", tout << "#" << l1->get_id() << " #" << l2->get_id() << " #" << l3->get_id(););
|
||||
if (m_params.m_bb_ext_gates) {
|
||||
if ((m().is_false(l1) && m().is_false(l2)) ||
|
||||
(m().is_false(l1) && m().is_false(l3)) ||
|
||||
(m().is_false(l2) && m().is_false(l3)))
|
||||
r = m().mk_false();
|
||||
else if ((m().is_true(l1) && m().is_true(l2)) ||
|
||||
(m().is_true(l1) && m().is_true(l3)) ||
|
||||
(m().is_true(l2) && m().is_true(l3)))
|
||||
r = m().mk_true();
|
||||
else if (l1 == l2 && l1 == l3)
|
||||
r = l1;
|
||||
else if (m().is_false(l1))
|
||||
s.mk_and(l2, l3, r);
|
||||
else if (m().is_false(l2))
|
||||
s.mk_and(l1, l3, r);
|
||||
else if (m().is_false(l3))
|
||||
s.mk_and(l1, l2, r);
|
||||
else if (m().is_true(l1))
|
||||
s.mk_or(l2, l3, r);
|
||||
else if (m().is_true(l2))
|
||||
s.mk_or(l1, l3, r);
|
||||
else if (m().is_true(l3))
|
||||
s.mk_or(l1, l2, r);
|
||||
else if (m().is_complement(l1, l2))
|
||||
r = l3;
|
||||
else if (m().is_complement(l1, l3))
|
||||
r = l2;
|
||||
else if (m().is_complement(l2, l3))
|
||||
r = l1;
|
||||
else
|
||||
r = m().mk_app(m_util.get_family_id(), OP_CARRY, l1, l2, l3);
|
||||
}
|
||||
else {
|
||||
expr_ref t1(m()), t2(m()), t3(m());
|
||||
s.mk_and(l1, l2, t1);
|
||||
s.mk_and(l1, l3, t2);
|
||||
s.mk_and(l2, l3, t3);
|
||||
s.mk_or(t1, t2, t3, r);
|
||||
}
|
||||
}
|
||||
|
||||
template class bit_blaster_tpl<bit_blaster_cfg>;
|
||||
|
||||
bit_blaster::bit_blaster(ast_manager & m, bit_blaster_params const & params):
|
||||
bit_blaster_tpl<bit_blaster_cfg>(bit_blaster_cfg(m_util, params, m_simp)),
|
||||
m_util(m),
|
||||
m_simp(m) {
|
||||
}
|
65
src/ast/rewriter/bit_blaster/bit_blaster.h
Normal file
65
src/ast/rewriter/bit_blaster/bit_blaster.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
bit_blaster.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-06-05.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _BIT_BLASTER_H_
|
||||
#define _BIT_BLASTER_H_
|
||||
|
||||
#include"basic_simplifier_plugin.h"
|
||||
#include"bit_blaster_params.h"
|
||||
#include"bit_blaster_tpl.h"
|
||||
#include"bv_decl_plugin.h"
|
||||
#include"rational.h"
|
||||
|
||||
class bit_blaster_cfg {
|
||||
public:
|
||||
typedef rational numeral;
|
||||
protected:
|
||||
bv_util & m_util;
|
||||
bit_blaster_params const & m_params;
|
||||
basic_simplifier_plugin & s;
|
||||
public:
|
||||
bit_blaster_cfg(bv_util & u, bit_blaster_params const & p, basic_simplifier_plugin & _s);
|
||||
|
||||
ast_manager & m() const { return m_util.get_manager(); }
|
||||
numeral power(unsigned n) const { return m_util.power_of_two(n); }
|
||||
void mk_xor(expr * a, expr * b, expr_ref & r) { s.mk_xor(a, b, r); }
|
||||
void mk_xor3(expr * a, expr * b, expr * c, expr_ref & r);
|
||||
void mk_carry(expr * a, expr * b, expr * c, expr_ref & r);
|
||||
void mk_iff(expr * a, expr * b, expr_ref & r) { s.mk_iff(a, b, r); }
|
||||
void mk_and(expr * a, expr * b, expr_ref & r) { s.mk_and(a, b, r); }
|
||||
void mk_and(expr * a, expr * b, expr * c, expr_ref & r) { s.mk_and(a, b, c, r); }
|
||||
void mk_and(unsigned sz, expr * const * args, expr_ref & r) { s.mk_and(sz, args, r); }
|
||||
void mk_or(expr * a, expr * b, expr_ref & r) { s.mk_or(a, b, r); }
|
||||
void mk_or(expr * a, expr * b, expr * c, expr_ref & r) { s.mk_or(a, b, c, r); }
|
||||
void mk_or(unsigned sz, expr * const * args, expr_ref & r) { s.mk_or(sz, args, r); }
|
||||
void mk_not(expr * a, expr_ref & r) { s.mk_not(a, r); }
|
||||
void mk_ite(expr * c, expr * t, expr * e, expr_ref & r) { s.mk_ite(c, t, e, r); }
|
||||
void mk_nand(expr * a, expr * b, expr_ref & r) { s.mk_nand(a, b, r); }
|
||||
void mk_nor(expr * a, expr * b, expr_ref & r) { s.mk_nor(a, b, r); }
|
||||
};
|
||||
|
||||
class bit_blaster : public bit_blaster_tpl<bit_blaster_cfg> {
|
||||
bv_util m_util;
|
||||
basic_simplifier_plugin m_simp;
|
||||
public:
|
||||
bit_blaster(ast_manager & m, bit_blaster_params const & params);
|
||||
bit_blaster_params const & get_params() const { return this->m_params; }
|
||||
};
|
||||
|
||||
#endif /* _BIT_BLASTER_H_ */
|
||||
|
649
src/ast/rewriter/bit_blaster/bit_blaster_rewriter.cpp
Normal file
649
src/ast/rewriter/bit_blaster/bit_blaster_rewriter.cpp
Normal file
|
@ -0,0 +1,649 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
bit_blaster_rewriter.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Bit-blasting rewriter
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2012-10-04
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#include"bit_blaster_rewriter.h"
|
||||
#include"bv_decl_plugin.h"
|
||||
#include"bit_blaster_tpl_def.h"
|
||||
#include"rewriter_def.h"
|
||||
#include"bool_rewriter.h"
|
||||
#include"ref_util.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
|
||||
struct blaster_cfg {
|
||||
typedef rational numeral;
|
||||
|
||||
bool_rewriter & m_rewriter;
|
||||
bv_util & m_util;
|
||||
blaster_cfg(bool_rewriter & r, bv_util & u):m_rewriter(r), m_util(u) {}
|
||||
|
||||
ast_manager & m() const { return m_util.get_manager(); }
|
||||
numeral power(unsigned n) const { return m_util.power_of_two(n); }
|
||||
void mk_xor(expr * a, expr * b, expr_ref & r) { m_rewriter.mk_xor(a, b, r); }
|
||||
void mk_xor3(expr * a, expr * b, expr * c, expr_ref & r) {
|
||||
expr_ref tmp(m());
|
||||
mk_xor(b, c, tmp);
|
||||
mk_xor(a, tmp, r);
|
||||
}
|
||||
void mk_iff(expr * a, expr * b, expr_ref & r) { m_rewriter.mk_iff(a, b, r); }
|
||||
void mk_and(expr * a, expr * b, expr_ref & r) { m_rewriter.mk_and(a, b, r); }
|
||||
void mk_and(expr * a, expr * b, expr * c, expr_ref & r) { m_rewriter.mk_and(a, b, c, r); }
|
||||
void mk_and(unsigned sz, expr * const * args, expr_ref & r) { m_rewriter.mk_and(sz, args, r); }
|
||||
void mk_or(expr * a, expr * b, expr_ref & r) { m_rewriter.mk_or(a, b, r); }
|
||||
void mk_or(expr * a, expr * b, expr * c, expr_ref & r) { m_rewriter.mk_or(a, b, c, r); }
|
||||
void mk_or(unsigned sz, expr * const * args, expr_ref & r) { m_rewriter.mk_or(sz, args, r); }
|
||||
void mk_not(expr * a, expr_ref & r) { m_rewriter.mk_not(a, r); }
|
||||
void mk_carry(expr * a, expr * b, expr * c, expr_ref & r) {
|
||||
expr_ref t1(m()), t2(m()), t3(m());
|
||||
#if 1
|
||||
mk_and(a, b, t1);
|
||||
mk_and(a, c, t2);
|
||||
mk_and(b, c, t3);
|
||||
mk_or(t1, t2, t3, r);
|
||||
#else
|
||||
mk_or(a, b, t1);
|
||||
mk_or(a, c, t2);
|
||||
mk_or(b, c, t3);
|
||||
mk_and(t1, t2, t3, r);
|
||||
#endif
|
||||
}
|
||||
void mk_ite(expr * c, expr * t, expr * e, expr_ref & r) { m_rewriter.mk_ite(c, t, e, r); }
|
||||
void mk_nand(expr * a, expr * b, expr_ref & r) { m_rewriter.mk_nand(a, b, r); }
|
||||
void mk_nor(expr * a, expr * b, expr_ref & r) { m_rewriter.mk_nor(a, b, r); }
|
||||
};
|
||||
|
||||
// CMW: GCC/LLVM do not like this definition because a symbol of the same name exists in assert_set_bit_blaster.o
|
||||
// template class bit_blaster_tpl<blaster_cfg>;
|
||||
|
||||
class blaster : public bit_blaster_tpl<blaster_cfg> {
|
||||
bool_rewriter m_rewriter;
|
||||
bv_util m_util;
|
||||
public:
|
||||
blaster(ast_manager & m):
|
||||
bit_blaster_tpl<blaster_cfg>(blaster_cfg(m_rewriter, m_util)),
|
||||
m_rewriter(m),
|
||||
m_util(m) {
|
||||
m_rewriter.set_flat(false);
|
||||
m_rewriter.set_elim_and(true);
|
||||
}
|
||||
|
||||
bv_util & butil() { return m_util; }
|
||||
};
|
||||
|
||||
struct blaster_rewriter_cfg : public default_rewriter_cfg {
|
||||
ast_manager & m_manager;
|
||||
blaster & m_blaster;
|
||||
expr_ref_vector m_in1;
|
||||
expr_ref_vector m_in2;
|
||||
expr_ref_vector m_out;
|
||||
obj_map<func_decl, expr*> m_const2bits;
|
||||
expr_ref_vector m_bindings;
|
||||
|
||||
bool m_blast_mul;
|
||||
bool m_blast_add;
|
||||
bool m_blast_quant;
|
||||
bool m_blast_full;
|
||||
unsigned long long m_max_memory;
|
||||
unsigned m_max_steps;
|
||||
|
||||
ast_manager & m() const { return m_manager; }
|
||||
bv_util & butil() { return m_blaster.butil(); }
|
||||
|
||||
void cleanup_buffers() {
|
||||
m_in1.finalize();
|
||||
m_in2.finalize();
|
||||
m_out.finalize();
|
||||
m_bindings.finalize();
|
||||
}
|
||||
|
||||
blaster_rewriter_cfg(ast_manager & m, blaster & b, params_ref const & p):
|
||||
m_manager(m),
|
||||
m_blaster(b),
|
||||
m_in1(m),
|
||||
m_in2(m),
|
||||
m_out(m),
|
||||
m_bindings(m) {
|
||||
updt_params(p);
|
||||
}
|
||||
|
||||
~blaster_rewriter_cfg() {
|
||||
dec_ref_map_key_values(m_manager, m_const2bits);
|
||||
}
|
||||
|
||||
void updt_params(params_ref const & p) {
|
||||
m_max_memory = megabytes_to_bytes(p.get_uint(":max-memory", UINT_MAX));
|
||||
m_max_steps = p.get_uint(":max-steps", UINT_MAX);
|
||||
m_blast_add = p.get_bool(":blast-add", true);
|
||||
m_blast_mul = p.get_bool(":blast-mul", true);
|
||||
m_blast_full = p.get_bool(":blast-full", false);
|
||||
m_blast_quant = p.get_bool(":blast-quant", false);
|
||||
m_blaster.set_max_memory(m_max_memory);
|
||||
}
|
||||
|
||||
bool rewrite_patterns() const { return true; }
|
||||
|
||||
bool max_steps_exceeded(unsigned num_steps) const {
|
||||
cooperate("bit blaster");
|
||||
if (memory::get_allocation_size() > m_max_memory)
|
||||
throw rewriter_exception(Z3_MAX_MEMORY_MSG);
|
||||
return num_steps > m_max_steps;
|
||||
}
|
||||
|
||||
void get_bits(expr * t, expr_ref_vector & out_bits) {
|
||||
if (butil().is_mkbv(t)) {
|
||||
out_bits.append(to_app(t)->get_num_args(), to_app(t)->get_args());
|
||||
}
|
||||
else {
|
||||
unsigned bv_size = butil().get_bv_size(t);
|
||||
for (unsigned i = 0; i < bv_size; i++) {
|
||||
parameter p(i);
|
||||
out_bits.push_back(m().mk_app(butil().get_family_id(), OP_BIT2BOOL, 1, &p, 1, &t));
|
||||
}
|
||||
SASSERT(bv_size == out_bits.size());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename V>
|
||||
app * mk_mkbv(V const & bits) {
|
||||
return m().mk_app(butil().get_family_id(), OP_MKBV, bits.size(), bits.c_ptr());
|
||||
}
|
||||
|
||||
void mk_const(func_decl * f, expr_ref & result) {
|
||||
SASSERT(f->get_family_id() == null_family_id);
|
||||
SASSERT(f->get_arity() == 0);
|
||||
expr * r;
|
||||
if (m_const2bits.find(f, r)) {
|
||||
result = r;
|
||||
return;
|
||||
}
|
||||
sort * s = f->get_range();
|
||||
SASSERT(butil().is_bv_sort(s));
|
||||
unsigned bv_size = butil().get_bv_size(s);
|
||||
sort * b = m().mk_bool_sort();
|
||||
m_out.reset();
|
||||
for (unsigned i = 0; i < bv_size; i++) {
|
||||
m_out.push_back(m().mk_fresh_const(0, b));
|
||||
}
|
||||
r = mk_mkbv(m_out);
|
||||
m_const2bits.insert(f, r);
|
||||
m_manager.inc_ref(f);
|
||||
m_manager.inc_ref(r);
|
||||
result = r;
|
||||
}
|
||||
|
||||
#define MK_UNARY_REDUCE(OP, BB_OP) \
|
||||
void OP(expr * arg, expr_ref & result) { \
|
||||
m_in1.reset(); \
|
||||
get_bits(arg, m_in1); \
|
||||
m_out.reset(); \
|
||||
m_blaster.BB_OP(m_in1.size(), m_in1.c_ptr(), m_out); \
|
||||
result = mk_mkbv(m_out); \
|
||||
}
|
||||
|
||||
MK_UNARY_REDUCE(reduce_not, mk_not);
|
||||
MK_UNARY_REDUCE(reduce_redor, mk_redor);
|
||||
MK_UNARY_REDUCE(reduce_redand, mk_redand);
|
||||
|
||||
#define MK_BIN_REDUCE(OP, BB_OP) \
|
||||
void OP(expr * arg1, expr * arg2, expr_ref & result) { \
|
||||
m_in1.reset(); m_in2.reset(); \
|
||||
get_bits(arg1, m_in1); \
|
||||
get_bits(arg2, m_in2); \
|
||||
m_out.reset(); \
|
||||
m_blaster.BB_OP(m_in1.size(), m_in1.c_ptr(), m_in2.c_ptr(), m_out); \
|
||||
result = mk_mkbv(m_out); \
|
||||
}
|
||||
|
||||
MK_BIN_REDUCE(reduce_shl, mk_shl);
|
||||
MK_BIN_REDUCE(reduce_ashr, mk_ashr);
|
||||
MK_BIN_REDUCE(reduce_lshr, mk_lshr);
|
||||
MK_BIN_REDUCE(reduce_udiv, mk_udiv);
|
||||
MK_BIN_REDUCE(reduce_urem, mk_urem);
|
||||
MK_BIN_REDUCE(reduce_sdiv, mk_sdiv);
|
||||
MK_BIN_REDUCE(reduce_srem, mk_srem);
|
||||
MK_BIN_REDUCE(reduce_smod, mk_smod);
|
||||
MK_BIN_REDUCE(reduce_ext_rotate_left, mk_ext_rotate_left);
|
||||
MK_BIN_REDUCE(reduce_ext_rotate_right, mk_ext_rotate_right);
|
||||
|
||||
#define MK_BIN_AC_REDUCE(OP, BIN_OP, BB_OP) \
|
||||
MK_BIN_REDUCE(BIN_OP, BB_OP); \
|
||||
void OP(unsigned num_args, expr * const * args, expr_ref & result) { \
|
||||
SASSERT(num_args > 0); \
|
||||
result = args[0]; \
|
||||
expr_ref new_result(m_manager); \
|
||||
for (unsigned i = 1; i < num_args; i++) { \
|
||||
BIN_OP(result.get(), args[i], new_result); \
|
||||
result = new_result; \
|
||||
} \
|
||||
}
|
||||
|
||||
MK_BIN_AC_REDUCE(reduce_add, reduce_bin_add, mk_adder);
|
||||
MK_BIN_AC_REDUCE(reduce_mul, reduce_bin_mul, mk_multiplier);
|
||||
|
||||
MK_BIN_AC_REDUCE(reduce_or, reduce_bin_or, mk_or);
|
||||
MK_BIN_AC_REDUCE(reduce_xor, reduce_bin_xor, mk_xor);
|
||||
|
||||
|
||||
#define MK_BIN_PRED_REDUCE(OP, BB_OP) \
|
||||
void OP(expr * arg1, expr * arg2, expr_ref & result) { \
|
||||
m_in1.reset(); m_in2.reset(); \
|
||||
get_bits(arg1, m_in1); \
|
||||
get_bits(arg2, m_in2); \
|
||||
m_blaster.BB_OP(m_in1.size(), m_in1.c_ptr(), m_in2.c_ptr(), result); \
|
||||
}
|
||||
|
||||
MK_BIN_PRED_REDUCE(reduce_eq, mk_eq);
|
||||
MK_BIN_PRED_REDUCE(reduce_sle, mk_sle);
|
||||
MK_BIN_PRED_REDUCE(reduce_ule, mk_ule);
|
||||
MK_BIN_PRED_REDUCE(reduce_umul_no_overflow, mk_umul_no_overflow);
|
||||
MK_BIN_PRED_REDUCE(reduce_smul_no_overflow, mk_smul_no_overflow);
|
||||
MK_BIN_PRED_REDUCE(reduce_smul_no_underflow, mk_smul_no_underflow);
|
||||
|
||||
#define MK_PARAMETRIC_UNARY_REDUCE(OP, BB_OP) \
|
||||
void OP(expr * arg, unsigned n, expr_ref & result) { \
|
||||
m_in1.reset(); \
|
||||
get_bits(arg, m_in1); \
|
||||
m_out.reset(); \
|
||||
m_blaster.BB_OP(m_in1.size(), m_in1.c_ptr(), n, m_out); \
|
||||
result = mk_mkbv(m_out); \
|
||||
}
|
||||
|
||||
MK_PARAMETRIC_UNARY_REDUCE(reduce_sign_extend, mk_sign_extend);
|
||||
|
||||
void reduce_ite(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) {
|
||||
m_in1.reset();
|
||||
m_in2.reset();
|
||||
get_bits(arg2, m_in1);
|
||||
get_bits(arg3, m_in2);
|
||||
m_out.reset();
|
||||
m_blaster.mk_multiplexer(arg1, m_in1.size(), m_in1.c_ptr(), m_in2.c_ptr(), m_out);
|
||||
result = mk_mkbv(m_out);
|
||||
}
|
||||
|
||||
void reduce_concat(unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
m_out.reset();
|
||||
unsigned i = num_args;
|
||||
while (i > 0) {
|
||||
i--;
|
||||
m_in1.reset();
|
||||
get_bits(args[i], m_in1);
|
||||
m_out.append(m_in1.size(), m_in1.c_ptr());
|
||||
}
|
||||
result = mk_mkbv(m_out);
|
||||
}
|
||||
|
||||
void reduce_extract(unsigned start, unsigned end, expr * arg, expr_ref & result) {
|
||||
m_in1.reset();
|
||||
get_bits(arg, m_in1);
|
||||
m_out.reset();
|
||||
for (unsigned i = start; i <= end; ++i)
|
||||
m_out.push_back(m_in1.get(i));
|
||||
result = mk_mkbv(m_out);
|
||||
}
|
||||
|
||||
void reduce_num(func_decl * f, expr_ref & result) {
|
||||
SASSERT(f->get_num_parameters() == 2);
|
||||
SASSERT(f->get_parameter(0).is_rational());
|
||||
SASSERT(f->get_parameter(1).is_int());
|
||||
rational v = f->get_parameter(0).get_rational();
|
||||
unsigned bv_sz = f->get_parameter(1).get_int();
|
||||
m_out.reset();
|
||||
m_blaster.num2bits(v, bv_sz, m_out);
|
||||
result = mk_mkbv(m_out);
|
||||
}
|
||||
|
||||
void throw_unsupported() {
|
||||
throw rewriter_exception("operator is not supported, you must simplify the goal before applying bit-blasting");
|
||||
}
|
||||
|
||||
void blast_bv_term(expr * t, expr_ref & result, proof_ref & result_pr) {
|
||||
ptr_buffer<expr> bits;
|
||||
unsigned bv_size = butil().get_bv_size(t);
|
||||
for (unsigned i = 0; i < bv_size; i++) {
|
||||
parameter p(i);
|
||||
bits.push_back(m().mk_app(butil().get_family_id(), OP_BIT2BOOL, 1, &p, 1, &t));
|
||||
}
|
||||
result = mk_mkbv(bits);
|
||||
result_pr = 0;
|
||||
}
|
||||
|
||||
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
|
||||
result_pr = 0;
|
||||
if (num == 0 && f->get_family_id() == null_family_id && butil().is_bv_sort(f->get_range())) {
|
||||
mk_const(f, result);
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
if (m().is_eq(f)) {
|
||||
SASSERT(num == 2);
|
||||
if (butil().is_bv(args[0])) {
|
||||
reduce_eq(args[0], args[1], result);
|
||||
return BR_DONE;
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
if (m().is_ite(f)) {
|
||||
SASSERT(num == 3);
|
||||
if (butil().is_bv(args[1])) {
|
||||
reduce_ite(args[0], args[1], args[2], result);
|
||||
return BR_DONE;
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
if (f->get_family_id() == butil().get_family_id()) {
|
||||
switch (f->get_decl_kind()) {
|
||||
case OP_BV_NUM:
|
||||
SASSERT(num == 0);
|
||||
reduce_num(f, result);
|
||||
return BR_DONE;
|
||||
case OP_BADD:
|
||||
if (!m_blast_add)
|
||||
return BR_FAILED;
|
||||
reduce_add(num, args, result);
|
||||
return BR_DONE;
|
||||
case OP_BMUL:
|
||||
if (!m_blast_mul)
|
||||
return BR_FAILED;
|
||||
reduce_mul(num, args, result);
|
||||
return BR_DONE;
|
||||
|
||||
case OP_BSDIV:
|
||||
case OP_BUDIV:
|
||||
case OP_BSREM:
|
||||
case OP_BUREM:
|
||||
case OP_BSMOD:
|
||||
if (m_blast_mul)
|
||||
throw_unsupported(); // must simplify to DIV_I AND DIV0
|
||||
return BR_FAILED; // keep them
|
||||
|
||||
case OP_BSDIV0:
|
||||
case OP_BUDIV0:
|
||||
case OP_BSREM0:
|
||||
case OP_BUREM0:
|
||||
case OP_BSMOD0:
|
||||
return BR_FAILED;
|
||||
|
||||
case OP_BSDIV_I:
|
||||
if (!m_blast_mul)
|
||||
return BR_FAILED;
|
||||
SASSERT(num == 2);
|
||||
reduce_sdiv(args[0], args[1], result);
|
||||
return BR_DONE;
|
||||
case OP_BUDIV_I:
|
||||
if (!m_blast_mul)
|
||||
return BR_FAILED;
|
||||
SASSERT(num == 2);
|
||||
reduce_udiv(args[0], args[1], result);
|
||||
return BR_DONE;
|
||||
case OP_BSREM_I:
|
||||
if (!m_blast_mul)
|
||||
return BR_FAILED;
|
||||
SASSERT(num == 2);
|
||||
reduce_srem(args[0], args[1], result);
|
||||
return BR_DONE;
|
||||
case OP_BUREM_I:
|
||||
if (!m_blast_mul)
|
||||
return BR_FAILED;
|
||||
SASSERT(num == 2);
|
||||
reduce_urem(args[0], args[1], result);
|
||||
return BR_DONE;
|
||||
case OP_BSMOD_I:
|
||||
if (!m_blast_mul)
|
||||
return BR_FAILED;
|
||||
SASSERT(num == 2);
|
||||
reduce_smod(args[0], args[1], result);
|
||||
return BR_DONE;
|
||||
case OP_ULEQ:
|
||||
SASSERT(num == 2);
|
||||
reduce_ule(args[0], args[1], result);
|
||||
return BR_DONE;
|
||||
case OP_SLEQ:
|
||||
SASSERT(num == 2);
|
||||
reduce_sle(args[0], args[1], result);
|
||||
return BR_DONE;
|
||||
case OP_BOR:
|
||||
reduce_or(num, args, result);
|
||||
return BR_DONE;
|
||||
case OP_BNOT:
|
||||
SASSERT(num == 1);
|
||||
reduce_not(args[0], result);
|
||||
return BR_DONE;
|
||||
case OP_BXOR:
|
||||
reduce_xor(num, args, result);
|
||||
return BR_DONE;
|
||||
|
||||
case OP_CONCAT:
|
||||
reduce_concat(num, args, result);
|
||||
return BR_DONE;
|
||||
case OP_SIGN_EXT:
|
||||
SASSERT(num == 1);
|
||||
reduce_sign_extend(args[0], f->get_parameter(0).get_int(), result);
|
||||
return BR_DONE;
|
||||
case OP_EXTRACT:
|
||||
SASSERT(num == 1);
|
||||
reduce_extract(f->get_parameter(1).get_int(), f->get_parameter(0).get_int(), args[0], result);
|
||||
return BR_DONE;
|
||||
|
||||
case OP_BREDOR:
|
||||
SASSERT(num == 1);
|
||||
reduce_redor(args[0], result);
|
||||
return BR_DONE;
|
||||
case OP_BREDAND:
|
||||
SASSERT(num == 1);
|
||||
reduce_redand(args[0], result);
|
||||
return BR_DONE;
|
||||
case OP_BSHL:
|
||||
SASSERT(num == 2);
|
||||
reduce_shl(args[0], args[1], result);
|
||||
return BR_DONE;
|
||||
case OP_BLSHR:
|
||||
SASSERT(num == 2);
|
||||
reduce_lshr(args[0], args[1], result);
|
||||
return BR_DONE;
|
||||
case OP_BASHR:
|
||||
SASSERT(num == 2);
|
||||
reduce_ashr(args[0], args[1], result);
|
||||
return BR_DONE;
|
||||
case OP_EXT_ROTATE_LEFT:
|
||||
SASSERT(num == 2);
|
||||
reduce_ext_rotate_left(args[0], args[1], result);
|
||||
return BR_DONE;
|
||||
case OP_EXT_ROTATE_RIGHT:
|
||||
SASSERT(num == 2);
|
||||
reduce_ext_rotate_right(args[0], args[1], result);
|
||||
return BR_DONE;
|
||||
|
||||
case OP_BUMUL_NO_OVFL:
|
||||
SASSERT(num == 2);
|
||||
reduce_umul_no_overflow(args[0], args[1], result);
|
||||
return BR_DONE;
|
||||
case OP_BSMUL_NO_OVFL:
|
||||
SASSERT(num == 2);
|
||||
reduce_smul_no_overflow(args[0], args[1], result);
|
||||
return BR_DONE;
|
||||
case OP_BSMUL_NO_UDFL:
|
||||
SASSERT(num == 2);
|
||||
reduce_smul_no_underflow(args[0], args[1], result);
|
||||
return BR_DONE;
|
||||
|
||||
case OP_BIT2BOOL:
|
||||
case OP_MKBV:
|
||||
case OP_INT2BV:
|
||||
case OP_BV2INT:
|
||||
return BR_FAILED;
|
||||
default:
|
||||
TRACE("bit_blaster", tout << "non-supported operator: " << f->get_name() << "\n";
|
||||
for (unsigned i = 0; i < num; i++) tout << mk_ismt2_pp(args[i], m()) << std::endl;);
|
||||
throw_unsupported();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_blast_full && butil().is_bv_sort(f->get_range())) {
|
||||
blast_bv_term(m().mk_app(f, num, args), result, result_pr);
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
bool pre_visit(expr * t) {
|
||||
if (m_blast_quant && is_quantifier(t)) {
|
||||
quantifier * q = to_quantifier(t);
|
||||
ptr_buffer<expr> new_bindings;
|
||||
ptr_buffer<expr> new_args;
|
||||
unsigned i = q->get_num_decls();
|
||||
unsigned j = 0;
|
||||
while (i > 0) {
|
||||
--i;
|
||||
sort * s = q->get_decl_sort(i);
|
||||
if (butil().is_bv_sort(s)) {
|
||||
unsigned bv_size = butil().get_bv_size(s);
|
||||
new_args.reset();
|
||||
for (unsigned k = 0; k < bv_size; k++) {
|
||||
new_args.push_back(m().mk_var(j, m().mk_bool_sort()));
|
||||
j++;
|
||||
}
|
||||
new_bindings.push_back(mk_mkbv(new_args));
|
||||
}
|
||||
else {
|
||||
new_bindings.push_back(m().mk_var(j, s));
|
||||
j++;
|
||||
}
|
||||
}
|
||||
SASSERT(new_bindings.size() == q->get_num_decls());
|
||||
i = q->get_num_decls();
|
||||
while (i > 0) {
|
||||
i--;
|
||||
m_bindings.push_back(new_bindings[i]);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool reduce_var(var * t, expr_ref & result, proof_ref & result_pr) {
|
||||
if (m_blast_quant) {
|
||||
if (t->get_idx() >= m_bindings.size())
|
||||
return false;
|
||||
result = m_bindings.get(m_bindings.size() - t->get_idx() - 1);
|
||||
result_pr = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_blast_full && butil().is_bv(t)) {
|
||||
blast_bv_term(t, result, result_pr);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool reduce_quantifier(quantifier * old_q,
|
||||
expr * new_body,
|
||||
expr * const * new_patterns,
|
||||
expr * const * new_no_patterns,
|
||||
expr_ref & result,
|
||||
proof_ref & result_pr) {
|
||||
if (!m_blast_quant)
|
||||
return false;
|
||||
unsigned curr_sz = m_bindings.size();
|
||||
SASSERT(old_q->get_num_decls() <= curr_sz);
|
||||
unsigned num_decls = old_q->get_num_decls();
|
||||
unsigned old_sz = curr_sz - num_decls;
|
||||
string_buffer<> name_buffer;
|
||||
ptr_buffer<sort> new_decl_sorts;
|
||||
sbuffer<symbol> new_decl_names;
|
||||
for (unsigned i = 0; i < num_decls; i++) {
|
||||
symbol const & n = old_q->get_decl_name(i);
|
||||
sort * s = old_q->get_decl_sort(i);
|
||||
if (butil().is_bv_sort(s)) {
|
||||
unsigned bv_size = butil().get_bv_size(s);
|
||||
for (unsigned j = 0; j < bv_size; j++) {
|
||||
name_buffer.reset();
|
||||
name_buffer << n << "." << j;
|
||||
new_decl_names.push_back(symbol(name_buffer.c_str()));
|
||||
new_decl_sorts.push_back(m().mk_bool_sort());
|
||||
}
|
||||
}
|
||||
else {
|
||||
new_decl_sorts.push_back(s);
|
||||
new_decl_names.push_back(n);
|
||||
}
|
||||
}
|
||||
result = m().mk_quantifier(old_q->is_forall(), new_decl_sorts.size(), new_decl_sorts.c_ptr(), new_decl_names.c_ptr(),
|
||||
new_body, old_q->get_weight(), old_q->get_qid(), old_q->get_skid(),
|
||||
old_q->get_num_patterns(), new_patterns, old_q->get_num_no_patterns(), new_no_patterns);
|
||||
result_pr = 0;
|
||||
m_bindings.shrink(old_sz);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// CMW: GCC/LLVM do not like this definition because a symbol of the same name exists in assert_set_bit_blaster.o
|
||||
// template class rewriter_tpl<blaster_rewriter_cfg>;
|
||||
|
||||
struct bit_blaster_rewriter::imp : public rewriter_tpl<blaster_rewriter_cfg> {
|
||||
blaster m_blaster;
|
||||
blaster_rewriter_cfg m_cfg;
|
||||
imp(ast_manager & m, params_ref const & p):
|
||||
rewriter_tpl<blaster_rewriter_cfg>(m,
|
||||
m.proofs_enabled(),
|
||||
m_cfg),
|
||||
m_blaster(m),
|
||||
m_cfg(m, m_blaster, p) {
|
||||
SASSERT(m_blaster.butil().get_family_id() == m.get_family_id("bv"));
|
||||
}
|
||||
};
|
||||
|
||||
bit_blaster_rewriter::bit_blaster_rewriter(ast_manager & m, params_ref const & p):
|
||||
m_imp(alloc(imp, m, p)) {
|
||||
}
|
||||
|
||||
bit_blaster_rewriter::~bit_blaster_rewriter() {
|
||||
dealloc(m_imp);
|
||||
}
|
||||
|
||||
void bit_blaster_rewriter::updt_params(params_ref const& p) {
|
||||
m_imp->m_cfg.updt_params(p);
|
||||
}
|
||||
|
||||
void bit_blaster_rewriter::set_cancel(bool f) {
|
||||
m_imp->set_cancel(f);
|
||||
m_imp->m_blaster.set_cancel(f);
|
||||
}
|
||||
|
||||
ast_manager & bit_blaster_rewriter::m() const {
|
||||
return m_imp->m();
|
||||
}
|
||||
|
||||
unsigned bit_blaster_rewriter::get_num_steps() const {
|
||||
return m_imp->get_num_steps();
|
||||
}
|
||||
|
||||
void bit_blaster_rewriter::cleanup() {
|
||||
m_imp->cleanup();
|
||||
}
|
||||
|
||||
obj_map<func_decl, expr*> const & bit_blaster_rewriter::const2bits() const {
|
||||
return m_imp->m_cfg.m_const2bits;
|
||||
}
|
||||
|
||||
void bit_blaster_rewriter::operator()(expr * e, expr_ref & result, proof_ref & result_proof) {
|
||||
m_imp->operator()(e, result, result_proof);
|
||||
}
|
||||
|
42
src/ast/rewriter/bit_blaster/bit_blaster_rewriter.h
Normal file
42
src/ast/rewriter/bit_blaster/bit_blaster_rewriter.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
bit_blaster_rewriter.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Bit-blasting rewriter
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2012-10-04
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#ifndef _BIT_BLASTER_REWRITER_H_
|
||||
#define _BIT_BLASTER_REWRITER_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"obj_hashtable.h"
|
||||
#include"params.h"
|
||||
|
||||
class bit_blaster_rewriter {
|
||||
struct imp;
|
||||
imp * m_imp;
|
||||
public:
|
||||
bit_blaster_rewriter(ast_manager & m, params_ref const & p);
|
||||
~bit_blaster_rewriter();
|
||||
void updt_params(params_ref const & p);
|
||||
void set_cancel(bool f);
|
||||
ast_manager & m() const;
|
||||
unsigned get_num_steps() const;
|
||||
void cleanup();
|
||||
obj_map<func_decl, expr*> const& const2bits() const;
|
||||
void operator()(expr * e, expr_ref & result, proof_ref & result_proof);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
134
src/ast/rewriter/bit_blaster/bit_blaster_tpl.h
Normal file
134
src/ast/rewriter/bit_blaster/bit_blaster_tpl.h
Normal file
|
@ -0,0 +1,134 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
bit_blaster_tpl.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Template for bit-blaster operations
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2011-05-02.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _BIT_BLASTER_TPL_H_
|
||||
#define _BIT_BLASTER_TPL_H_
|
||||
|
||||
#include"rational.h"
|
||||
|
||||
template<typename Cfg>
|
||||
class bit_blaster_tpl : public Cfg {
|
||||
public:
|
||||
typedef rational numeral;
|
||||
protected:
|
||||
template<bool Signed>
|
||||
void mk_le(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref & out);
|
||||
|
||||
template<unsigned k>
|
||||
void mk_sdiv_srem_smod(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits);
|
||||
|
||||
template<bool Left>
|
||||
void mk_ext_rotate_left_right(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits);
|
||||
|
||||
unsigned long long m_max_memory;
|
||||
volatile bool m_cancel;
|
||||
bool m_use_wtm; /* Wallace Tree Multiplier */
|
||||
bool m_use_bcm; /* Booth Multiplier for constants */
|
||||
void checkpoint();
|
||||
|
||||
public:
|
||||
bit_blaster_tpl(Cfg const & cfg = Cfg(), unsigned long long max_memory = UINT64_MAX, bool use_wtm = false, bool use_bcm=false):
|
||||
Cfg(cfg),
|
||||
m_max_memory(max_memory),
|
||||
m_cancel(false),
|
||||
m_use_wtm(use_wtm),
|
||||
m_use_bcm(use_bcm) {
|
||||
}
|
||||
|
||||
void set_max_memory(unsigned long long max_memory) {
|
||||
m_max_memory = max_memory;
|
||||
}
|
||||
|
||||
void set_cancel(bool f) { m_cancel = f; }
|
||||
void cancel() { set_cancel(true); }
|
||||
void reset_cancel() { set_cancel(false); }
|
||||
|
||||
// Cfg required API
|
||||
ast_manager & m() const { return Cfg::m(); }
|
||||
numeral power(unsigned n) const { return Cfg::power(n); }
|
||||
void mk_xor(expr * a, expr * b, expr_ref & r) { Cfg::mk_xor(a, b, r); }
|
||||
void mk_xor3(expr * a, expr * b, expr * c, expr_ref & r) { Cfg::mk_xor3(a, b, c, r); }
|
||||
void mk_carry(expr * a, expr * b, expr * c, expr_ref & r) { Cfg::mk_carry(a, b, c, r); }
|
||||
void mk_iff(expr * a, expr * b, expr_ref & r) { Cfg::mk_iff(a, b, r); }
|
||||
void mk_and(expr * a, expr * b, expr_ref & r) { Cfg::mk_and(a, b, r); }
|
||||
void mk_and(expr * a, expr * b, expr * c, expr_ref & r) { Cfg::mk_and(a, b, c, r); }
|
||||
void mk_and(unsigned sz, expr * const * args, expr_ref & r) { Cfg::mk_and(sz, args, r); }
|
||||
void mk_or(expr * a, expr * b, expr_ref & r) { Cfg::mk_or(a, b, r); }
|
||||
void mk_or(expr * a, expr * b, expr * c, expr_ref & r) { Cfg::mk_or(a, b, c, r); }
|
||||
void mk_or(unsigned sz, expr * const * args, expr_ref & r) { Cfg::mk_or(sz, args, r); }
|
||||
void mk_not(expr * a, expr_ref & r) { Cfg::mk_not(a, r); }
|
||||
void mk_ite(expr * c, expr * t, expr * e, expr_ref & r) { Cfg::mk_ite(c, t, e, r); }
|
||||
void mk_nand(expr * a, expr * b, expr_ref & r) { Cfg::mk_nand(a, b, r); }
|
||||
void mk_nor(expr * a, expr * b, expr_ref & r) { Cfg::mk_nor(a, b, r); }
|
||||
//
|
||||
|
||||
|
||||
bool is_numeral(unsigned sz, expr * const * bits) const;
|
||||
bool is_numeral(unsigned sz, expr * const * bits, numeral & r) const;
|
||||
bool is_minus_one(unsigned sz, expr * const * bits) const;
|
||||
void num2bits(numeral const & v, unsigned sz, expr_ref_vector & out_bits) const;
|
||||
|
||||
void mk_half_adder(expr * a, expr * b, expr_ref & out, expr_ref & cout);
|
||||
void mk_full_adder(expr * a, expr * b, expr * cin, expr_ref & out, expr_ref & cout);
|
||||
void mk_neg(unsigned sz, expr * const * a_bits, expr_ref_vector & out_bits);
|
||||
void mk_adder(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits);
|
||||
void mk_subtracter(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits, expr_ref & cout);
|
||||
void mk_multiplier(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits);
|
||||
void mk_udiv_urem(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & q_bits, expr_ref_vector & r_bits);
|
||||
void mk_udiv(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & q_bits);
|
||||
void mk_urem(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & r_bits);
|
||||
void mk_multiplexer(expr * c, unsigned sz, expr * const * t_bits, expr * const * e_bits, expr_ref_vector & out_bits);
|
||||
void mk_sdiv(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits);
|
||||
void mk_srem(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits);
|
||||
void mk_smod(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits);
|
||||
void mk_rotate_left(unsigned sz, expr * const * a_bits, unsigned n, expr_ref_vector & out_bits);
|
||||
void mk_rotate_right(unsigned sz, expr * const * a_bits, unsigned n, expr_ref_vector & out_bits);
|
||||
void mk_ext_rotate_left(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits);
|
||||
void mk_ext_rotate_right(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits);
|
||||
void mk_sign_extend(unsigned sz, expr * const * a_bits, unsigned n, expr_ref_vector & out_bits);
|
||||
void mk_zero_extend(unsigned sz, expr * const * a_bits, unsigned n, expr_ref_vector & out_bits);
|
||||
void mk_eq(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref & out);
|
||||
void mk_is_eq(unsigned sz, expr * const * a_bits, unsigned n, expr_ref & out);
|
||||
void mk_eqs(unsigned sz, expr * const * a_bits, expr_ref_vector & eqs);
|
||||
void mk_shl(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits);
|
||||
void mk_lshr(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits);
|
||||
void mk_ashr(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits);
|
||||
void mk_sle(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref & out);
|
||||
void mk_ule(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref & out);
|
||||
void mk_not(unsigned sz, expr * const * a_bits, expr_ref_vector & out_bits);
|
||||
void mk_and(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits);
|
||||
void mk_or(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits);
|
||||
void mk_xor(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits);
|
||||
void mk_xnor(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits);
|
||||
void mk_nand(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits);
|
||||
void mk_nor(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits);
|
||||
void mk_redand(unsigned sz, expr * const * a_bits, expr_ref_vector & out_bits);
|
||||
void mk_redor(unsigned sz, expr * const * a_bits, expr_ref_vector & out_bits);
|
||||
void mk_umul_no_overflow(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref & out);
|
||||
void mk_smul_no_overflow_core(unsigned sz, expr * const * a_bits, expr * const * b_bits, bool is_overflow, expr_ref & result);
|
||||
void mk_smul_no_overflow(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref & out);
|
||||
void mk_smul_no_underflow(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref & out);
|
||||
void mk_comp(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits);
|
||||
|
||||
void mk_carry_save_adder(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr * const * c_bits, expr_ref_vector & sum_bits, expr_ref_vector & carry_bits);
|
||||
void mk_const_multiplier(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits);
|
||||
|
||||
void mk_abs(unsigned sz, expr * const * a_bits, expr_ref_vector & out_bits);
|
||||
};
|
||||
|
||||
#endif
|
1203
src/ast/rewriter/bit_blaster/bit_blaster_tpl_def.h
Normal file
1203
src/ast/rewriter/bit_blaster/bit_blaster_tpl_def.h
Normal file
File diff suppressed because it is too large
Load diff
436
src/ast/rewriter/bit_blaster/eager_bit_blaster.cpp
Normal file
436
src/ast/rewriter/bit_blaster/eager_bit_blaster.cpp
Normal file
|
@ -0,0 +1,436 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
eager_bit_blaster.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-10-02.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include"ast_ll_pp.h"
|
||||
#include"eager_bit_blaster.h"
|
||||
|
||||
eager_bit_blaster::basic_plugin::basic_plugin(ast_manager & m, eager_bit_blaster::bv_plugin & p, basic_simplifier_plugin & s):
|
||||
simplifier_plugin(symbol("basic"), m),
|
||||
m_main(p),
|
||||
m_s(s) {
|
||||
}
|
||||
|
||||
eager_bit_blaster::basic_plugin::~basic_plugin() {
|
||||
}
|
||||
|
||||
bool eager_bit_blaster::basic_plugin::reduce(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
if (f->get_decl_kind() == OP_ITE) {
|
||||
SASSERT(num_args == 3);
|
||||
return m_main.reduce_ite(args[0], args[1], args[2], result);
|
||||
}
|
||||
else if (f->get_decl_kind() == OP_NOT) {
|
||||
// the internalizer assumes there is not double negation (not (not x))
|
||||
SASSERT(num_args == 1);
|
||||
m_s.mk_not(args[0], result);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
eager_bit_blaster::bv_plugin::bv_plugin(ast_manager & m, bit_blaster_params const & p):
|
||||
simplifier_plugin(symbol("bv"), m),
|
||||
m_util(m),
|
||||
m_bb(m, p),
|
||||
m_s(m) {
|
||||
}
|
||||
|
||||
eager_bit_blaster::bv_plugin::~bv_plugin() {
|
||||
}
|
||||
|
||||
void eager_bit_blaster::bv_plugin::get_bits(expr * n, expr_ref_vector & out_bits) {
|
||||
rational val;
|
||||
unsigned bv_size;
|
||||
if (m_util.is_numeral(n, val, bv_size)) {
|
||||
TRACE("eager_bb_bug", tout << "bv_size: " << bv_size << "\n";);
|
||||
m_bb.num2bits(val, bv_size, out_bits);
|
||||
SASSERT(out_bits.size() == bv_size);
|
||||
}
|
||||
else if (m_util.is_mkbv(n)) {
|
||||
out_bits.append(to_app(n)->get_num_args(), to_app(n)->get_args());
|
||||
}
|
||||
else {
|
||||
unsigned bv_size = m_util.get_bv_size(n);
|
||||
for (unsigned i = 0; i < bv_size; i++) {
|
||||
parameter p(i);
|
||||
out_bits.push_back(m_manager.mk_app(get_family_id(), OP_BIT2BOOL, 1, &p, 1, &n));
|
||||
}
|
||||
SASSERT(bv_size == out_bits.size());
|
||||
}
|
||||
}
|
||||
|
||||
inline app * eager_bit_blaster::bv_plugin::mk_mkbv(expr_ref_vector const & bits) {
|
||||
#ifdef Z3DEBUG
|
||||
for (unsigned i = 0; i < bits.size(); i++) {
|
||||
expr * b = bits.get(i);
|
||||
SASSERT(!m_manager.is_not(b) || !m_manager.is_not(to_app(b)->get_arg(0)));
|
||||
}
|
||||
#endif
|
||||
return m_manager.mk_app(get_family_id(), OP_MKBV, bits.size(), bits.c_ptr());
|
||||
}
|
||||
|
||||
#define MK_UNARY_REDUCE(OP, BB_OP) \
|
||||
void eager_bit_blaster::bv_plugin::OP(expr * arg, expr_ref & result) { \
|
||||
expr_ref_vector bits(m_manager); \
|
||||
get_bits(arg, bits); \
|
||||
expr_ref_vector out_bits(m_manager); \
|
||||
m_bb.BB_OP(bits.size(), bits.c_ptr(), out_bits); \
|
||||
result = mk_mkbv(out_bits); \
|
||||
}
|
||||
|
||||
#define MK_BIN_REDUCE(OP, BB_OP) \
|
||||
void eager_bit_blaster::bv_plugin::OP(expr * arg1, expr * arg2, expr_ref & result) { \
|
||||
expr_ref_vector bits1(m_manager); \
|
||||
expr_ref_vector bits2(m_manager); \
|
||||
get_bits(arg1, bits1); \
|
||||
get_bits(arg2, bits2); \
|
||||
expr_ref_vector out_bits(m_manager); \
|
||||
m_bb.BB_OP(bits1.size(), bits1.c_ptr(), bits2.c_ptr(), out_bits); \
|
||||
result = mk_mkbv(out_bits); \
|
||||
}
|
||||
|
||||
#define MK_BIN_AC_FLAT_REDUCE(OP, BIN_OP, S_OP, BB_OP) \
|
||||
MK_BIN_REDUCE(BIN_OP, BB_OP); \
|
||||
void eager_bit_blaster::bv_plugin::OP(unsigned num_args, expr * const * args, expr_ref & result) { \
|
||||
SASSERT(num_args > 0); \
|
||||
if (num_args == 2) { \
|
||||
BIN_OP(args[0], args[1], result); \
|
||||
return; \
|
||||
} \
|
||||
\
|
||||
ptr_buffer<expr_ref_vector> args_bits; \
|
||||
for (unsigned i = 0; i < num_args; i++) { \
|
||||
expr_ref_vector * bits = alloc(expr_ref_vector, m_manager); \
|
||||
get_bits(args[i], *bits); \
|
||||
args_bits.push_back(bits); \
|
||||
} \
|
||||
\
|
||||
unsigned bv_size = m_util.get_bv_size(args[0]); \
|
||||
expr_ref_vector new_bits(m_manager); \
|
||||
for (unsigned i = 0; i < bv_size; i++) { \
|
||||
expr_ref_vector arg_bits(m_manager); \
|
||||
for (unsigned j = 0; j < num_args; j++) \
|
||||
arg_bits.push_back(args_bits[j]->get(i)); \
|
||||
expr_ref new_bit(m_manager); \
|
||||
m_s.S_OP(arg_bits.size(), arg_bits.c_ptr(), new_bit); \
|
||||
new_bits.push_back(new_bit); \
|
||||
} \
|
||||
result = mk_mkbv(new_bits); \
|
||||
std::for_each(args_bits.begin(), args_bits.end(), delete_proc<expr_ref_vector>()); \
|
||||
}
|
||||
|
||||
#define MK_BIN_AC_REDUCE(OP, BIN_OP, BB_OP) \
|
||||
MK_BIN_REDUCE(BIN_OP, BB_OP); \
|
||||
void eager_bit_blaster::bv_plugin::OP(unsigned num_args, expr * const * args, expr_ref & result) { \
|
||||
SASSERT(num_args > 0); \
|
||||
result = args[0]; \
|
||||
for (unsigned i = 1; i < num_args; i++) { \
|
||||
expr_ref new_result(m_manager); \
|
||||
BIN_OP(result.get(), args[i], new_result); \
|
||||
result = new_result; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define MK_BIN_PRED_REDUCE(OP, BB_OP) \
|
||||
void eager_bit_blaster::bv_plugin::OP(expr * arg1, expr * arg2, expr_ref & result) { \
|
||||
expr_ref_vector bits1(m_manager); \
|
||||
expr_ref_vector bits2(m_manager); \
|
||||
get_bits(arg1, bits1); \
|
||||
get_bits(arg2, bits2); \
|
||||
m_bb.BB_OP(bits1.size(), bits1.c_ptr(), bits2.c_ptr(), result); \
|
||||
}
|
||||
|
||||
#define MK_PARAMETRIC_UNARY_REDUCE(OP, BB_OP) \
|
||||
void eager_bit_blaster::bv_plugin::OP(expr * arg, unsigned n, expr_ref & result) { \
|
||||
expr_ref_vector bits(m_manager); \
|
||||
get_bits(arg, bits); \
|
||||
expr_ref_vector out_bits(m_manager); \
|
||||
m_bb.BB_OP(bits.size(), bits.c_ptr(), n, out_bits); \
|
||||
result = mk_mkbv(out_bits); \
|
||||
}
|
||||
|
||||
MK_UNARY_REDUCE(reduce_not, mk_not);
|
||||
MK_BIN_AC_FLAT_REDUCE(reduce_or, reduce_bin_or, mk_or, mk_or);
|
||||
MK_BIN_AC_FLAT_REDUCE(reduce_and, reduce_bin_and, mk_and, mk_and);
|
||||
MK_BIN_AC_FLAT_REDUCE(reduce_nor, reduce_bin_nor, mk_nor, mk_nor);
|
||||
MK_BIN_AC_FLAT_REDUCE(reduce_nand, reduce_bin_nand, mk_nand, mk_nand);
|
||||
MK_BIN_REDUCE(reduce_xor, mk_xor);
|
||||
MK_BIN_REDUCE(reduce_xnor, mk_xnor);
|
||||
MK_UNARY_REDUCE(reduce_neg, mk_neg);
|
||||
MK_BIN_AC_REDUCE(reduce_add, reduce_bin_add, mk_adder);
|
||||
MK_BIN_AC_REDUCE(reduce_mul, reduce_bin_mul, mk_multiplier);
|
||||
MK_BIN_PRED_REDUCE(reduce_sle, mk_sle);
|
||||
MK_BIN_PRED_REDUCE(reduce_ule, mk_ule);
|
||||
MK_PARAMETRIC_UNARY_REDUCE(reduce_rotate_left, mk_rotate_left);
|
||||
MK_PARAMETRIC_UNARY_REDUCE(reduce_rotate_right, mk_rotate_right);
|
||||
MK_PARAMETRIC_UNARY_REDUCE(reduce_sign_extend, mk_sign_extend);
|
||||
MK_PARAMETRIC_UNARY_REDUCE(reduce_zero_extend, mk_zero_extend);
|
||||
MK_UNARY_REDUCE(reduce_redor, mk_redor);
|
||||
MK_UNARY_REDUCE(reduce_redand, mk_redand);
|
||||
MK_BIN_REDUCE(reduce_shl, mk_shl);
|
||||
MK_BIN_REDUCE(reduce_ashr, mk_ashr);
|
||||
MK_BIN_REDUCE(reduce_lshr, mk_lshr);
|
||||
MK_BIN_REDUCE(reduce_comp, mk_comp);
|
||||
MK_BIN_REDUCE(reduce_udiv, mk_udiv);
|
||||
MK_BIN_REDUCE(reduce_urem, mk_urem);
|
||||
MK_BIN_REDUCE(reduce_sdiv, mk_sdiv);
|
||||
MK_BIN_REDUCE(reduce_srem, mk_srem);
|
||||
MK_BIN_REDUCE(reduce_smod, mk_smod);
|
||||
|
||||
void eager_bit_blaster::bv_plugin::reduce_extract(unsigned start, unsigned end, expr * arg, expr_ref & result) {
|
||||
expr_ref_vector bits(m_manager);
|
||||
get_bits(arg, bits);
|
||||
expr_ref_vector out_bits(m_manager);
|
||||
for (unsigned i = start; i <= end; ++i)
|
||||
out_bits.push_back(bits.get(i));
|
||||
result = mk_mkbv(out_bits);
|
||||
}
|
||||
|
||||
void eager_bit_blaster::bv_plugin::reduce_concat(unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
expr_ref_vector out_bits(m_manager);
|
||||
unsigned i = num_args;
|
||||
while (i > 0) {
|
||||
i--;
|
||||
expr_ref_vector bits(m_manager);
|
||||
get_bits(args[i], bits);
|
||||
out_bits.append(bits.size(), bits.c_ptr());
|
||||
}
|
||||
result = mk_mkbv(out_bits);
|
||||
}
|
||||
|
||||
bool eager_bit_blaster::bv_plugin::reduce_ite(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) {
|
||||
sort * s = m_manager.get_sort(arg2);
|
||||
if (!m_util.is_bv_sort(s))
|
||||
return false;
|
||||
expr_ref_vector bits1(m_manager);
|
||||
expr_ref_vector bits2(m_manager);
|
||||
get_bits(arg2, bits1);
|
||||
get_bits(arg3, bits2);
|
||||
SASSERT(bits1.size() == bits2.size());
|
||||
expr_ref_vector out_bits(m_manager);
|
||||
unsigned bv_size = bits1.size();
|
||||
for (unsigned i = 0; i < bv_size; i++) {
|
||||
expr_ref new_bit(m_manager);
|
||||
m_s.mk_ite(arg1, bits1.get(i), bits2.get(i), new_bit);
|
||||
out_bits.push_back(new_bit);
|
||||
}
|
||||
result = mk_mkbv(out_bits);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool eager_bit_blaster::bv_plugin::reduce(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
bv_op_kind k = static_cast<bv_op_kind>(f->get_decl_kind());
|
||||
switch (k) {
|
||||
case OP_BNOT:
|
||||
SASSERT(num_args == 1);
|
||||
reduce_not(args[0], result);
|
||||
return true;
|
||||
case OP_BOR:
|
||||
reduce_or(num_args, args, result);
|
||||
return true;
|
||||
case OP_BAND:
|
||||
reduce_and(num_args, args, result);
|
||||
return true;
|
||||
case OP_BNOR:
|
||||
reduce_nor(num_args, args, result);
|
||||
return true;
|
||||
case OP_BNAND:
|
||||
reduce_nand(num_args, args, result);
|
||||
return true;
|
||||
case OP_BXOR:
|
||||
SASSERT(num_args == 2);
|
||||
reduce_xor(args[0], args[1], result);
|
||||
return true;
|
||||
case OP_BXNOR:
|
||||
SASSERT(num_args == 2);
|
||||
reduce_xnor(args[0], args[1], result);
|
||||
return true;
|
||||
case OP_BNEG:
|
||||
SASSERT(num_args == 1);
|
||||
reduce_neg(args[0], result);
|
||||
return true;
|
||||
case OP_BADD:
|
||||
reduce_add(num_args, args, result);
|
||||
return true;
|
||||
case OP_BMUL:
|
||||
reduce_mul(num_args, args, result);
|
||||
return true;
|
||||
case OP_BIT1:
|
||||
case OP_BIT0:
|
||||
case OP_BSUB:
|
||||
// I'm assuming the expressions were simplified before invoking this method.
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
case OP_BSDIV:
|
||||
case OP_BUDIV:
|
||||
case OP_BSREM:
|
||||
case OP_BUREM:
|
||||
case OP_BSMOD:
|
||||
// I'm assuming the expressions were simplified before invoking this method.
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
case OP_BSDIV0:
|
||||
case OP_BUDIV0:
|
||||
case OP_BSREM0:
|
||||
case OP_BUREM0:
|
||||
case OP_BSMOD0:
|
||||
// do nothing... these are uninterpreted
|
||||
return true;
|
||||
case OP_BSDIV_I:
|
||||
SASSERT(num_args == 2);
|
||||
reduce_sdiv(args[0], args[1], result);
|
||||
return true;
|
||||
case OP_BUDIV_I:
|
||||
SASSERT(num_args == 2);
|
||||
reduce_udiv(args[0], args[1], result);
|
||||
return true;
|
||||
case OP_BSREM_I:
|
||||
SASSERT(num_args == 2);
|
||||
reduce_srem(args[0], args[1], result);
|
||||
return true;
|
||||
case OP_BUREM_I:
|
||||
SASSERT(num_args == 2);
|
||||
reduce_urem(args[0], args[1], result);
|
||||
return true;
|
||||
case OP_BSMOD_I:
|
||||
SASSERT(num_args == 2);
|
||||
reduce_smod(args[0], args[1], result);
|
||||
return true;
|
||||
case OP_ULEQ:
|
||||
SASSERT(num_args == 2);
|
||||
reduce_ule(args[0], args[1], result);
|
||||
return true;
|
||||
case OP_SLEQ:
|
||||
SASSERT(num_args == 2);
|
||||
reduce_sle(args[0], args[1], result);
|
||||
return true;
|
||||
case OP_UGEQ:
|
||||
case OP_SGEQ:
|
||||
case OP_ULT:
|
||||
case OP_SLT:
|
||||
case OP_UGT:
|
||||
case OP_SGT:
|
||||
// I'm assuming the expressions were simplified before invoking this method.
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
case OP_EXTRACT:
|
||||
SASSERT(num_args == 1);
|
||||
reduce_extract(f->get_parameter(1).get_int(), f->get_parameter(0).get_int(), args[0], result);
|
||||
return true;
|
||||
case OP_CONCAT:
|
||||
reduce_concat(num_args, args, result);
|
||||
return true;
|
||||
case OP_SIGN_EXT:
|
||||
SASSERT(num_args == 1);
|
||||
reduce_sign_extend(args[0], f->get_parameter(0).get_int(), result);
|
||||
return true;
|
||||
case OP_ZERO_EXT:
|
||||
SASSERT(num_args == 1);
|
||||
reduce_zero_extend(args[0], f->get_parameter(0).get_int(), result);
|
||||
return true;
|
||||
case OP_REPEAT:
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
case OP_BREDOR:
|
||||
SASSERT(num_args == 1);
|
||||
reduce_redor(args[0], result);
|
||||
return true;
|
||||
case OP_BREDAND:
|
||||
SASSERT(num_args == 1);
|
||||
reduce_redand(args[0], result);
|
||||
return true;
|
||||
case OP_BCOMP:
|
||||
SASSERT(num_args == 2);
|
||||
reduce_comp(args[0], args[1], result);
|
||||
return true;
|
||||
case OP_BSHL:
|
||||
SASSERT(num_args == 2);
|
||||
reduce_shl(args[0], args[1], result);
|
||||
return true;
|
||||
case OP_BLSHR:
|
||||
SASSERT(num_args == 2);
|
||||
reduce_lshr(args[0], args[1], result);
|
||||
return true;
|
||||
case OP_BASHR:
|
||||
SASSERT(num_args == 2);
|
||||
reduce_ashr(args[0], args[1], result);
|
||||
return true;
|
||||
case OP_ROTATE_LEFT:
|
||||
SASSERT(num_args == 1);
|
||||
reduce_rotate_left(args[0], f->get_parameter(0).get_int(), result);
|
||||
return true;
|
||||
case OP_ROTATE_RIGHT:
|
||||
SASSERT(num_args == 1);
|
||||
reduce_rotate_right(args[0], f->get_parameter(0).get_int(), result);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool eager_bit_blaster::bv_plugin::reduce_eq(expr * lhs, expr * rhs, expr_ref & result) {
|
||||
TRACE("eager_bb_eq", tout << mk_ll_pp(lhs, m_manager) << "\n" << mk_ll_pp(rhs, m_manager) << "\n";);
|
||||
SASSERT(m_util.get_bv_size(lhs) == m_util.get_bv_size(rhs));
|
||||
expr_ref_vector bits1(m_manager);
|
||||
expr_ref_vector bits2(m_manager);
|
||||
get_bits(lhs, bits1);
|
||||
get_bits(rhs, bits2);
|
||||
SASSERT(bits1.size() == bits2.size());
|
||||
m_bb.mk_eq(bits1.size(), bits1.c_ptr(), bits2.c_ptr(), result);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool eager_bit_blaster::bv_plugin::reduce_distinct(unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
if (num_args <= 1) {
|
||||
result = m_manager.mk_true();
|
||||
}
|
||||
if (num_args == 2) {
|
||||
expr_ref tmp(m_manager);
|
||||
reduce_eq(args[0], args[1], tmp);
|
||||
m_s.mk_not(tmp, result);
|
||||
}
|
||||
else {
|
||||
expr_ref_vector new_args(m_manager);
|
||||
for (unsigned i = 0; i < num_args - 1; i++) {
|
||||
expr * a1 = args[i];
|
||||
for (unsigned j = i + 1; j < num_args; j++) {
|
||||
expr * a2 = args[j];
|
||||
expr_ref tmp1(m_manager);
|
||||
reduce_eq(a1, a2, tmp1);
|
||||
expr_ref tmp2(m_manager);
|
||||
m_s.mk_not(tmp1, tmp2);
|
||||
new_args.push_back(tmp2);
|
||||
}
|
||||
}
|
||||
m_s.mk_and(new_args.size(), new_args.c_ptr(), result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
eager_bit_blaster::eager_bit_blaster(ast_manager & m, bit_blaster_params const & p):
|
||||
m_simplifier(m) {
|
||||
m_simplifier.enable_ac_support(false);
|
||||
bv_plugin * bv_p = alloc(bv_plugin, m, p);
|
||||
m_simplifier.register_plugin(bv_p);
|
||||
m_simplifier.register_plugin(alloc(basic_plugin, m, *bv_p, bv_p->get_basic_simplifier()));
|
||||
}
|
||||
|
||||
void eager_bit_blaster::operator()(expr * s, expr_ref & r, proof_ref & p) {
|
||||
m_simplifier.operator()(s, r, p);
|
||||
}
|
||||
|
107
src/ast/rewriter/bit_blaster/eager_bit_blaster.h
Normal file
107
src/ast/rewriter/bit_blaster/eager_bit_blaster.h
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
eager_bit_blaster.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-10-02.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _EAGER_BIT_BLASTER_H_
|
||||
#define _EAGER_BIT_BLASTER_H_
|
||||
|
||||
#include"bv_decl_plugin.h"
|
||||
#include"bit_blaster.h"
|
||||
#include"simplifier.h"
|
||||
#include"basic_simplifier_plugin.h"
|
||||
|
||||
class eager_bit_blaster {
|
||||
|
||||
class bv_plugin : public simplifier_plugin {
|
||||
bv_util m_util;
|
||||
bit_blaster m_bb;
|
||||
basic_simplifier_plugin m_s;
|
||||
|
||||
void get_bits(expr * n, expr_ref_vector & out_bits);
|
||||
app * mk_mkbv(expr_ref_vector const & bits);
|
||||
|
||||
void reduce_not(expr * arg, expr_ref & result);
|
||||
void reduce_bin_or(expr * arg1, expr * arg2, expr_ref & result);
|
||||
void reduce_or(unsigned num_args, expr * const * args, expr_ref & result);
|
||||
void reduce_bin_and(expr * arg1, expr * arg2, expr_ref & result);
|
||||
void reduce_and(unsigned num_args, expr * const * args, expr_ref & result);
|
||||
void reduce_bin_nor(expr * arg1, expr * arg2, expr_ref & result);
|
||||
void reduce_nor(unsigned num_args, expr * const * args, expr_ref & result);
|
||||
void reduce_bin_nand(expr * arg1, expr * arg2, expr_ref & result);
|
||||
void reduce_nand(unsigned num_args, expr * const * args, expr_ref & result);
|
||||
void reduce_xor(expr * arg1, expr * arg2, expr_ref & result);
|
||||
void reduce_xnor(expr * arg1, expr * arg2, expr_ref & result);
|
||||
|
||||
void reduce_neg(expr * arg, expr_ref & result);
|
||||
void reduce_bin_add(expr * arg1, expr * arg2, expr_ref & result);
|
||||
void reduce_add(unsigned num_args, expr * const * args, expr_ref & result);
|
||||
void reduce_bin_mul(expr * arg1, expr * arg2, expr_ref & result);
|
||||
void reduce_mul(unsigned num_args, expr * const * args, expr_ref & result);
|
||||
void reduce_sdiv(expr * arg1, expr * arg2, expr_ref & result);
|
||||
void reduce_udiv(expr * arg1, expr * arg2, expr_ref & result);
|
||||
void reduce_srem(expr * arg1, expr * arg2, expr_ref & result);
|
||||
void reduce_urem(expr * arg1, expr * arg2, expr_ref & result);
|
||||
void reduce_smod(expr * arg1, expr * arg2, expr_ref & result);
|
||||
void reduce_sle(expr * arg1, expr * arg2, expr_ref & result);
|
||||
void reduce_ule(expr * arg1, expr * arg2, expr_ref & result);
|
||||
|
||||
void reduce_concat(unsigned num_args, expr * const * args, expr_ref & result);
|
||||
void reduce_extract(unsigned start, unsigned end, expr * arg, expr_ref & result);
|
||||
|
||||
void reduce_redor(expr * arg, expr_ref & result);
|
||||
void reduce_redand(expr * arg, expr_ref & result);
|
||||
|
||||
void reduce_comp(expr * arg1, expr * arg2, expr_ref & result);
|
||||
void reduce_shl(expr * arg1, expr * arg2, expr_ref & result);
|
||||
void reduce_ashr(expr * arg1, expr * arg2, expr_ref & result);
|
||||
void reduce_lshr(expr * arg1, expr * arg2, expr_ref & result);
|
||||
|
||||
void reduce_rotate_left(expr * arg, unsigned n, expr_ref & result);
|
||||
void reduce_rotate_right(expr * arg, unsigned n, expr_ref & result);
|
||||
void reduce_sign_extend(expr * arg, unsigned n, expr_ref & result);
|
||||
void reduce_zero_extend(expr * arg, unsigned n, expr_ref & result);
|
||||
|
||||
public:
|
||||
bv_plugin(ast_manager & m, bit_blaster_params const & p);
|
||||
virtual ~bv_plugin();
|
||||
virtual bool reduce(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);
|
||||
virtual bool reduce_eq(expr * lhs, expr * rhs, expr_ref & result);
|
||||
virtual bool reduce_distinct(unsigned num_args, expr * const * args, expr_ref & result);
|
||||
basic_simplifier_plugin & get_basic_simplifier() { return m_s; }
|
||||
bool reduce_ite(expr * arg1, expr * arg2, expr * arg3, expr_ref & result);
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Plugin for handling the term-ite.
|
||||
*/
|
||||
class basic_plugin : public simplifier_plugin {
|
||||
bv_plugin & m_main;
|
||||
basic_simplifier_plugin & m_s;
|
||||
public:
|
||||
basic_plugin(ast_manager & m, bv_plugin & p, basic_simplifier_plugin & s);
|
||||
virtual ~basic_plugin();
|
||||
virtual bool reduce(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);
|
||||
};
|
||||
|
||||
simplifier m_simplifier;
|
||||
public:
|
||||
eager_bit_blaster(ast_manager & m, bit_blaster_params const & p);
|
||||
void operator()(expr * s, expr_ref & r, proof_ref & p);
|
||||
};
|
||||
|
||||
#endif /* _EAGER_BIT_BLASTER_H_ */
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue