mirror of
https://github.com/Z3Prover/z3
synced 2025-04-24 01:25:31 +00:00
extend constant folding for bit-vector overflow/underflow operators, #657
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
41edf5f91e
commit
914bf2ff3b
10 changed files with 332 additions and 57 deletions
|
@ -522,7 +522,7 @@ void array_decl_plugin::get_sort_names(svector<builtin_name>& sort_names, symbol
|
|||
void array_decl_plugin::get_op_names(svector<builtin_name>& op_names, symbol const & logic) {
|
||||
op_names.push_back(builtin_name("store",OP_STORE));
|
||||
op_names.push_back(builtin_name("select",OP_SELECT));
|
||||
if (logic == symbol::null) {
|
||||
if (true || logic == symbol::null) {
|
||||
// none of the SMT2 logics support these extensions
|
||||
op_names.push_back(builtin_name("const",OP_CONST_ARRAY));
|
||||
op_names.push_back(builtin_name("map",OP_ARRAY_MAP));
|
||||
|
|
|
@ -20,8 +20,8 @@ Revision History:
|
|||
#define BIT_BLASTER_H_
|
||||
|
||||
#include"bool_rewriter.h"
|
||||
#include"bit_blaster_params.h"
|
||||
#include"bit_blaster_tpl.h"
|
||||
#include"bit_blaster/bit_blaster_params.h"
|
||||
#include"bit_blaster/bit_blaster_tpl.h"
|
||||
#include"bv_decl_plugin.h"
|
||||
#include"rational.h"
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ Notes:
|
|||
#include"bv_rewriter_params.hpp"
|
||||
#include"poly_rewriter_def.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include"bit_blaster/bit_blaster.h"
|
||||
|
||||
|
||||
void bv_rewriter::updt_local_params(params_ref const & _p) {
|
||||
|
@ -189,6 +190,15 @@ br_status bv_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * cons
|
|||
return mk_bv_comp(args[0], args[1], result);
|
||||
case OP_MKBV:
|
||||
return mk_mkbv(num_args, args, result);
|
||||
case OP_BUMUL_NO_OVFL:
|
||||
SASSERT(num_args == 2);
|
||||
return mk_bv_umul_no_ovfl(args[0], args[1], result);
|
||||
case OP_BSMUL_NO_OVFL:
|
||||
SASSERT(num_args == 2);
|
||||
return mk_bv_smul_no_ovfl(args[0], args[1], result);
|
||||
case OP_BSMUL_NO_UDFL:
|
||||
SASSERT(num_args == 2);
|
||||
return mk_bv_smul_no_udfl(args[0], args[1], result);
|
||||
default:
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
@ -1100,6 +1110,92 @@ br_status bv_rewriter::mk_concat(unsigned num_args, expr * const * args, expr_re
|
|||
return BR_DONE;
|
||||
}
|
||||
|
||||
br_status bv_rewriter::mk_bv_umul_no_ovfl(expr * arg1, expr * arg2, expr_ref& result) {
|
||||
rational val1, val2;
|
||||
unsigned bv_size;
|
||||
bool is_num1 = is_numeral(arg1, val1, bv_size);
|
||||
bool is_num2 = is_numeral(arg2, val2, bv_size);
|
||||
if (is_num1 && (val1.is_zero() || val1.is_one())) {
|
||||
result = m().mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
if (is_num2 && (val2.is_zero() || val2.is_one())) {
|
||||
result = m().mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
if (is_num1 && is_num2) {
|
||||
SASSERT(!val1.is_neg());
|
||||
SASSERT(!val2.is_neg());
|
||||
rational r = val1 * val2;
|
||||
result = m().mk_bool_val(r < rational(2).expt(bv_size));
|
||||
return BR_DONE;
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status bv_rewriter::mk_bv_smul_no_ovfl(expr * arg1, expr * arg2, expr_ref& result) {
|
||||
rational val1, val2;
|
||||
unsigned bv_size;
|
||||
bool is_num1 = is_numeral(arg1, val1, bv_size);
|
||||
bool is_num2 = is_numeral(arg2, val2, bv_size);
|
||||
if (is_num1 && (val1.is_zero() || val1.is_one())) {
|
||||
result = m().mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
if (is_num2 && (val2.is_zero() || val2.is_one())) {
|
||||
result = m().mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
if (is_num1 && is_num2) {
|
||||
bit_blaster_params params;
|
||||
bit_blaster blaster(m(), params);
|
||||
SASSERT(!val1.is_neg());
|
||||
SASSERT(!val2.is_neg());
|
||||
expr_ref_vector bits1(m()), bits2(m());
|
||||
for (unsigned i = 0; i < bv_size; ++i) {
|
||||
bits1.push_back(m().mk_bool_val(!val1.is_even()));
|
||||
bits2.push_back(m().mk_bool_val(!val2.is_even()));
|
||||
val1 = div(val1, rational(2));
|
||||
val2 = div(val2, rational(2));
|
||||
}
|
||||
blaster.mk_smul_no_overflow(bits1.size(), bits1.c_ptr(), bits2.c_ptr(), result);
|
||||
return BR_DONE;
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status bv_rewriter::mk_bv_smul_no_udfl(expr * arg1, expr * arg2, expr_ref& result) {
|
||||
rational val1, val2;
|
||||
unsigned bv_size;
|
||||
bool is_num1 = is_numeral(arg1, val1, bv_size);
|
||||
bool is_num2 = is_numeral(arg2, val2, bv_size);
|
||||
if (is_num1 && (val1.is_zero() || val1.is_one())) {
|
||||
result = m().mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
if (is_num2 && (val2.is_zero() || val2.is_one())) {
|
||||
result = m().mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
if (is_num1 && is_num2) {
|
||||
bit_blaster_params params;
|
||||
bit_blaster blaster(m(), params);
|
||||
SASSERT(!val1.is_neg());
|
||||
SASSERT(!val2.is_neg());
|
||||
expr_ref_vector bits1(m()), bits2(m());
|
||||
for (unsigned i = 0; i < bv_size; ++i) {
|
||||
bits1.push_back(m().mk_bool_val(!val1.is_even()));
|
||||
bits2.push_back(m().mk_bool_val(!val2.is_even()));
|
||||
val1 = div(val1, rational(2));
|
||||
val2 = div(val2, rational(2));
|
||||
}
|
||||
blaster.mk_smul_no_underflow(bits1.size(), bits1.c_ptr(), bits2.c_ptr(), result);
|
||||
return BR_DONE;
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
|
||||
br_status bv_rewriter::mk_zero_extend(unsigned n, expr * arg, expr_ref & result) {
|
||||
if (n == 0) {
|
||||
result = arg;
|
||||
|
|
|
@ -114,6 +114,9 @@ class bv_rewriter : public poly_rewriter<bv_rewriter_core> {
|
|||
br_status mk_bv_srem_i(expr * arg1, expr * arg2, expr_ref & result) { return mk_bv_srem_core(arg1, arg2, true, result); }
|
||||
br_status mk_bv_urem_i(expr * arg1, expr * arg2, expr_ref & result) { return mk_bv_urem_core(arg1, arg2, true, result); }
|
||||
br_status mk_bv_smod_i(expr * arg1, expr * arg2, expr_ref & result) { return mk_bv_smod_core(arg1, arg2, true, result); }
|
||||
br_status mk_bv_umul_no_ovfl(expr * arg1, expr * arg2, expr_ref& result);
|
||||
br_status mk_bv_smul_no_ovfl(expr * arg1, expr * arg2, expr_ref& result);
|
||||
br_status mk_bv_smul_no_udfl(expr * arg1, expr * arg2, expr_ref& result);
|
||||
br_status mk_int2bv(unsigned bv_size, expr * arg, expr_ref & result);
|
||||
br_status mk_bv2int(expr * arg, expr_ref & result);
|
||||
br_status mk_bv_redor(expr * arg, expr_ref & result);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue