10#ifndef KLEE_METASMTBUILDER_H
11#define KLEE_METASMTBUILDER_H
15#include "klee/Config/config.h"
23#include "llvm/Support/CommandLine.h"
25#include <metaSMT/frontend/Logic.hpp>
26#include <metaSMT/frontend/QF_BV.hpp>
27#include <metaSMT/frontend/Array.hpp>
29using namespace metaSMT;
30using namespace metaSMT::logic::QF_BV;
35llvm::cl::opt<bool> UseConstructHashMetaSMT(
36 "use-construct-hash-metasmt",
37 llvm::cl::desc(
"Use hash-consing during metaSMT query construction."),
38 llvm::cl::init(
true));
43typedef metaSMT::logic::Predicate<proto::terminal<
44 metaSMT::logic::tag::true_tag>::type>
const MetaSMTConstTrue;
45typedef metaSMT::logic::Predicate<proto::terminal<
46 metaSMT::logic::tag::false_tag>::type>
const MetaSMTConstFalse;
47typedef metaSMT::logic::Array::array MetaSMTArray;
49template <
typename SolverContext>
class MetaSMTBuilder;
51template <
typename SolverContext>
52class MetaSMTArrayExprHash
53 :
public ArrayExprHash<typename SolverContext::result_type> {
55 friend class MetaSMTBuilder<SolverContext>;
58 MetaSMTArrayExprHash(){};
59 virtual ~MetaSMTArrayExprHash(){};
62template <
typename SolverContext>
class MetaSMTBuilder {
64 MetaSMTBuilder(SolverContext &solver,
bool optimizeDivides)
65 : _solver(solver), _optimizeDivides(optimizeDivides){};
66 virtual ~MetaSMTBuilder(){};
68 typename SolverContext::result_type construct(ref<Expr> e);
70 typename SolverContext::result_type getInitialRead(
const Array *root,
73 typename SolverContext::result_type getTrue() {
74 return (evaluate(_solver, metaSMT::logic::True));
77 typename SolverContext::result_type getFalse() {
78 return (evaluate(_solver, metaSMT::logic::False));
81 typename SolverContext::result_type bvOne(
unsigned width) {
82 return bvZExtConst(width, 1);
85 typename SolverContext::result_type bvZero(
unsigned width) {
86 return bvZExtConst(width, 0);
89 typename SolverContext::result_type bvMinusOne(
unsigned width) {
90 return bvSExtConst(width, (int64_t)-1);
93 typename SolverContext::result_type bvConst32(
unsigned width,
95 return (evaluate(_solver, bvuint(value, width)));
98 typename SolverContext::result_type bvConst64(
unsigned width,
100 return (evaluate(_solver, bvuint(value, width)));
103 typename SolverContext::result_type bvZExtConst(
unsigned width,
105 typename SolverContext::result_type bvSExtConst(
unsigned width,
109 typename SolverContext::result_type
110 bvLeftShift(
typename SolverContext::result_type expr,
unsigned width,
112 typename SolverContext::result_type
113 bvRightShift(
typename SolverContext::result_type expr,
unsigned width,
115 typename SolverContext::result_type
116 bvVarLeftShift(
typename SolverContext::result_type expr,
117 typename SolverContext::result_type shift,
unsigned width);
118 typename SolverContext::result_type
119 bvVarRightShift(
typename SolverContext::result_type expr,
120 typename SolverContext::result_type shift,
unsigned width);
121 typename SolverContext::result_type
122 bvVarArithRightShift(
typename SolverContext::result_type expr,
123 typename SolverContext::result_type shift,
126 typename SolverContext::result_type getArrayForUpdate(
const Array *root,
127 const UpdateNode *un);
128 typename SolverContext::result_type getInitialArray(
const Array *root);
129 MetaSMTArray buildArray(
unsigned elem_width,
unsigned index_width);
132 typedef ExprHashMap<std::pair<typename SolverContext::result_type, unsigned> >
134 typedef typename MetaSMTExprHashMap::iterator MetaSMTExprHashMapIter;
135 typedef typename MetaSMTExprHashMap::const_iterator
136 MetaSMTExprHashMapConstIter;
138 SolverContext &_solver;
139 bool _optimizeDivides;
140 MetaSMTArrayExprHash<SolverContext> _arr_hash;
141 MetaSMTExprHashMap _constructed;
143 typename SolverContext::result_type constructActual(ref<Expr> e,
145 typename SolverContext::result_type construct(ref<Expr> e,
int *width_out);
147 typename SolverContext::result_type
148 bvBoolExtract(
typename SolverContext::result_type expr,
int bit);
149 typename SolverContext::result_type
150 bvExtract(
typename SolverContext::result_type expr,
unsigned top,
152 typename SolverContext::result_type
153 eqExpr(
typename SolverContext::result_type a,
154 typename SolverContext::result_type b);
156 typename SolverContext::result_type
157 constructAShrByConstant(
typename SolverContext::result_type expr,
158 unsigned width,
unsigned shift,
159 typename SolverContext::result_type isSigned);
160 typename SolverContext::result_type
161 constructMulByConstant(
typename SolverContext::result_type expr,
162 unsigned width, uint64_t x);
163 typename SolverContext::result_type
164 constructUDivByConstant(
typename SolverContext::result_type expr_n,
165 unsigned width, uint64_t d);
166 typename SolverContext::result_type
167 constructSDivByConstant(
typename SolverContext::result_type expr_n,
168 unsigned width, uint64_t d);
171template <
typename SolverContext>
172typename SolverContext::result_type
173MetaSMTBuilder<SolverContext>::getArrayForUpdate(
const Array *root,
174 const UpdateNode *un) {
177 return (getInitialArray(root));
179 typename SolverContext::result_type un_expr;
180 bool hashed = _arr_hash.lookupUpdateNodeExpr(un, un_expr);
183 un_expr = evaluate(_solver,
184 metaSMT::logic::Array::store(
185 getArrayForUpdate(root, un->next.get()),
186 construct(un->index, 0), construct(un->value, 0)));
187 _arr_hash.hashUpdateNodeExpr(un, un_expr);
193template <
typename SolverContext>
194typename SolverContext::result_type
195MetaSMTBuilder<SolverContext>::getInitialArray(
const Array *root) {
197 typename SolverContext::result_type array_expr;
198 bool hashed = _arr_hash.lookupArrayExpr(root, array_expr);
203 evaluate(_solver, buildArray(root->getRange(), root->getDomain()));
205 if (root->isConstantArray()) {
206 for (
unsigned i = 0, e = root->size; i != e; ++i) {
207 typename SolverContext::result_type tmp = evaluate(
209 metaSMT::logic::Array::store(
212 construct(root->constantValues[i], 0)));
216 _arr_hash.hashArrayExpr(root, array_expr);
222template <
typename SolverContext>
223MetaSMTArray MetaSMTBuilder<SolverContext>::buildArray(
unsigned elem_width,
224 unsigned index_width) {
225 return (metaSMT::logic::Array::new_array(elem_width, index_width));
228template <
typename SolverContext>
229typename SolverContext::result_type
230MetaSMTBuilder<SolverContext>::getInitialRead(
const Array *root,
234 typename SolverContext::result_type array_exp = getInitialArray(root);
235 typename SolverContext::result_type res =
236 evaluate(_solver, metaSMT::logic::Array::select(
237 array_exp, bvuint(index, root->getDomain())));
241template <
typename SolverContext>
242typename SolverContext::result_type
243MetaSMTBuilder<SolverContext>::bvZExtConst(
unsigned width, uint64_t value) {
245 typename SolverContext::result_type res;
248 res = bvConst64(width, value);
250 typename SolverContext::result_type expr = bvConst64(64, value);
251 typename SolverContext::result_type zero = bvConst64(64, 0);
253 for (width -= 64; width > 64; width -= 64) {
254 expr = evaluate(_solver, concat(zero, expr));
256 res = evaluate(_solver, concat(bvConst64(width, 0), expr));
262template <
typename SolverContext>
263typename SolverContext::result_type
264MetaSMTBuilder<SolverContext>::bvSExtConst(
unsigned width, uint64_t value) {
266 typename SolverContext::result_type res;
269 res = bvConst64(width, value);
273 res = evaluate(_solver, sign_extend(width - 64, bvConst64(64, value)));
278template <
typename SolverContext>
279typename SolverContext::result_type
280MetaSMTBuilder<SolverContext>::bvBoolExtract(
281 typename SolverContext::result_type expr,
int bit) {
282 return (evaluate(_solver,
283 metaSMT::logic::equal(extract(bit, bit, expr), bvOne(1))));
286template <
typename SolverContext>
287typename SolverContext::result_type MetaSMTBuilder<SolverContext>::bvExtract(
288 typename SolverContext::result_type expr,
unsigned top,
unsigned bottom) {
289 return (evaluate(_solver, extract(top, bottom, expr)));
292template <
typename SolverContext>
293typename SolverContext::result_type
294MetaSMTBuilder<SolverContext>::eqExpr(
typename SolverContext::result_type a,
295 typename SolverContext::result_type b) {
296 return (evaluate(_solver, metaSMT::logic::equal(a, b)));
299template <
typename SolverContext>
300typename SolverContext::result_type
301MetaSMTBuilder<SolverContext>::constructAShrByConstant(
302 typename SolverContext::result_type expr,
unsigned width,
unsigned shift,
303 typename SolverContext::result_type isSigned) {
304 typename SolverContext::result_type res;
308 }
else if (shift >= width) {
313 metaSMT::logic::Ite(isSigned, concat(bvMinusOne(shift),
314 bvExtract(expr, width - 1, shift)),
315 bvRightShift(expr, width, shift)));
322template <
typename SolverContext>
323typename SolverContext::result_type
324MetaSMTBuilder<SolverContext>::constructMulByConstant(
325 typename SolverContext::result_type expr,
unsigned width, uint64_t x) {
328 typename SolverContext::result_type res;
338 for (
int j = 63; j >= 0; j--) {
339 uint64_t bit = 1LL << j;
341 if ((
add & bit) || (
sub & bit)) {
342 assert(!((
add & bit) && (
sub & bit)) &&
"invalid mult constants");
344 typename SolverContext::result_type op = bvLeftShift(expr, width, j);
348 res = evaluate(_solver, bvadd(res, op));
355 res = evaluate(_solver, bvsub(res, op));
358 res = evaluate(_solver, bvsub(bvZero(width), op));
385template <
typename SolverContext>
386typename SolverContext::result_type
387MetaSMTBuilder<SolverContext>::constructUDivByConstant(
388 typename SolverContext::result_type expr_n,
unsigned width, uint64_t d) {
390 assert(width == 32 &&
"can only compute udiv constants for 32-bit division");
394 uint32_t mprime, sh1, sh2;
396 typename SolverContext::result_type expr_sh1 = bvConst32(32, sh1);
397 typename SolverContext::result_type expr_sh2 = bvConst32(32, sh2);
400 typename SolverContext::result_type expr_n_64 =
401 evaluate(_solver, concat(bvZero(32), expr_n));
402 typename SolverContext::result_type t1_64bits =
403 constructMulByConstant(expr_n_64, 64, (uint64_t)mprime);
404 typename SolverContext::result_type t1 =
405 bvExtract(t1_64bits, 63, 32);
408 typename SolverContext::result_type n_minus_t1 =
409 evaluate(_solver, bvsub(expr_n, t1));
410 typename SolverContext::result_type shift_sh1 =
411 bvVarRightShift(n_minus_t1, expr_sh1, 32);
412 typename SolverContext::result_type plus_t1 =
413 evaluate(_solver, bvadd(shift_sh1, t1));
414 typename SolverContext::result_type res =
415 bvVarRightShift(plus_t1, expr_sh2, 32);
433template <
typename SolverContext>
434typename SolverContext::result_type
435MetaSMTBuilder<SolverContext>::constructSDivByConstant(
436 typename SolverContext::result_type expr_n,
unsigned width, uint64_t d) {
438 assert(width == 32 &&
"can only compute udiv constants for 32-bit division");
442 int32_t mprime, dsign, shpost;
444 typename SolverContext::result_type expr_dsign = bvConst32(32, dsign);
445 typename SolverContext::result_type expr_shpost = bvConst32(64, shpost);
448 int64_t mprime_64 = (int64_t)mprime;
452 typename SolverContext::result_type expr_n_64 =
453 evaluate(_solver, sign_extend(64 - width, expr_n));
454 typename SolverContext::result_type mult_64 =
455 constructMulByConstant(expr_n_64, 64, mprime_64);
456 typename SolverContext::result_type mulsh =
457 bvExtract(mult_64, 63, 32);
458 typename SolverContext::result_type n_plus_mulsh =
459 evaluate(_solver, bvadd(expr_n, mulsh));
462 typename SolverContext::result_type extend_npm =
463 evaluate(_solver, sign_extend(64 - width, n_plus_mulsh));
464 typename SolverContext::result_type shift_npm =
465 bvVarRightShift(extend_npm, expr_shpost, 64);
466 typename SolverContext::result_type shift_shpost =
467 bvExtract(shift_npm, 31, 0);
472 typename SolverContext::result_type is_signed = bvBoolExtract(expr_n, 31);
473 typename SolverContext::result_type neg_one = bvMinusOne(32);
474 typename SolverContext::result_type xsign_of_n =
475 evaluate(_solver, metaSMT::logic::Ite(is_signed, neg_one, bvZero(32)));
478 typename SolverContext::result_type q0 =
479 evaluate(_solver, bvsub(shift_shpost, xsign_of_n));
482 typename SolverContext::result_type q0_xor_dsign =
483 evaluate(_solver, bvxor(q0, expr_dsign));
484 typename SolverContext::result_type res =
485 evaluate(_solver, bvsub(q0_xor_dsign, expr_dsign));
490template <
typename SolverContext>
491typename SolverContext::result_type MetaSMTBuilder<SolverContext>::bvLeftShift(
492 typename SolverContext::result_type expr,
unsigned width,
unsigned shift) {
494 typename SolverContext::result_type res;
498 }
else if (shift >= width) {
503 res = evaluate(_solver,
504 concat(extract(width - shift - 1, 0, expr), bvZero(shift)));
510template <
typename SolverContext>
511typename SolverContext::result_type MetaSMTBuilder<SolverContext>::bvRightShift(
512 typename SolverContext::result_type expr,
unsigned width,
unsigned shift) {
514 typename SolverContext::result_type res;
518 }
else if (shift >= width) {
521 res = evaluate(_solver,
522 concat(bvZero(shift), extract(width - 1, shift, expr)));
529template <
typename SolverContext>
530typename SolverContext::result_type
531MetaSMTBuilder<SolverContext>::bvVarLeftShift(
532 typename SolverContext::result_type expr,
533 typename SolverContext::result_type shift,
unsigned width) {
535 assert(_solver.get_bv_width(expr) == width);
536 assert(_solver.get_bv_width(shift) == width);
539 return evaluate(_solver,
540 metaSMT::logic::Ite(bvult(shift, bvConst32(width, width)),
541 bvshl(expr, shift), bvZero(width)));
546template <
typename SolverContext>
547typename SolverContext::result_type
548MetaSMTBuilder<SolverContext>::bvVarRightShift(
549 typename SolverContext::result_type expr,
550 typename SolverContext::result_type shift,
unsigned width) {
552 assert(_solver.get_bv_width(expr) == width);
553 assert(_solver.get_bv_width(shift) == width);
556 return evaluate(_solver,
557 metaSMT::logic::Ite(bvult(shift, bvConst32(width, width)),
558 bvshr(expr, shift), bvZero(width)));
563template <
typename SolverContext>
564typename SolverContext::result_type
565MetaSMTBuilder<SolverContext>::bvVarArithRightShift(
566 typename SolverContext::result_type expr,
567 typename SolverContext::result_type shift,
unsigned width) {
569 assert(_solver.get_bv_width(expr) == width);
570 assert(_solver.get_bv_width(shift) == width);
573 return evaluate(_solver,
574 metaSMT::logic::Ite(bvult(shift, bvConst32(width, width)),
575 bvashr(expr, shift), bvZero(width)));
578template <
typename SolverContext>
579typename SolverContext::result_type
580MetaSMTBuilder<SolverContext>::construct(ref<Expr> e) {
581 typename SolverContext::result_type res = construct(e, 0);
582 _constructed.clear();
588template <
typename SolverContext>
589typename SolverContext::result_type
590MetaSMTBuilder<SolverContext>::construct(ref<Expr> e,
int *width_out) {
592 if (!UseConstructHashMetaSMT || isa<ConstantExpr>(e)) {
593 return (constructActual(e, width_out));
595 MetaSMTExprHashMapIter it = _constructed.find(e);
596 if (it != _constructed.end()) {
598 *width_out = it->second.second;
600 return it->second.first;
606 typename SolverContext::result_type res = constructActual(e, width_out);
607 _constructed.insert(std::make_pair(e, std::make_pair(res, *width_out)));
613template <
typename SolverContext>
614typename SolverContext::result_type
615MetaSMTBuilder<SolverContext>::constructActual(ref<Expr> e,
int *width_out) {
617 typename SolverContext::result_type res;
631 switch (e->getKind()) {
634 ConstantExpr *coe = cast<ConstantExpr>(e);
636 unsigned coe_width = coe->getWidth();
637 *width_out = coe_width;
640 if (coe_width == 1) {
641 res = (coe->isTrue()) ? getTrue() : getFalse();
642 }
else if (coe_width <= 32) {
643 res = bvConst32(coe_width, coe->getZExtValue(32));
644 }
else if (coe_width <= 64) {
645 res = bvConst64(coe_width, coe->getZExtValue());
647 ref<ConstantExpr> tmp = coe;
648 res = bvConst64(64, tmp->Extract(0, 64)->getZExtValue());
649 while (tmp->getWidth() > 64) {
650 tmp = tmp->Extract(64, tmp->getWidth() - 64);
651 unsigned min_width = std::min(64U, tmp->getWidth());
652 res = evaluate(_solver,
653 concat(bvConst64(min_width, tmp->Extract(0, min_width)
662 NotOptimizedExpr *noe = cast<NotOptimizedExpr>(e);
664 res = construct(noe->src, width_out);
669 SelectExpr *se = cast<SelectExpr>(e);
671 res = evaluate(_solver,
672 metaSMT::logic::Ite(construct(se->cond, 0),
673 construct(se->trueExpr, width_out),
674 construct(se->falseExpr, width_out)));
679 ReadExpr *re = cast<ReadExpr>(e);
680 assert(re && re->updates.root);
681 *width_out = re->updates.root->getRange();
683 res = evaluate(_solver, metaSMT::logic::Array::select(
684 getArrayForUpdate(re->updates.root,
685 re->updates.head.get()),
686 construct(re->index, 0)));
691 ConcatExpr *ce = cast<ConcatExpr>(e);
693 *width_out = ce->getWidth();
694 unsigned numKids = ce->getNumKids();
697 res = evaluate(_solver, construct(ce->getKid(numKids - 1), 0));
698 for (
int i = numKids - 2; i >= 0; i--) {
699 res = evaluate(_solver, concat(construct(ce->getKid(i), 0), res));
706 ExtractExpr *ee = cast<ExtractExpr>(e);
709 typename SolverContext::result_type child =
710 evaluate(_solver, construct(ee->expr, width_out));
712 unsigned ee_width = ee->getWidth();
713 *width_out = ee_width;
716 res = bvBoolExtract(child, ee->offset);
718 res = evaluate(_solver,
719 extract(ee->offset + ee_width - 1, ee->offset, child));
725 CastExpr *ce = cast<CastExpr>(e);
729 typename SolverContext::result_type child =
730 evaluate(_solver, construct(ce->src, &child_width));
732 unsigned ce_width = ce->getWidth();
733 *width_out = ce_width;
735 if (child_width == 1) {
736 res = evaluate(_solver, metaSMT::logic::Ite(child, bvOne(ce_width),
739 res = evaluate(_solver, zero_extend(ce_width - child_width, child));
753 CastExpr *ce = cast<CastExpr>(e);
757 typename SolverContext::result_type child =
758 evaluate(_solver, construct(ce->src, &child_width));
760 unsigned ce_width = ce->getWidth();
761 *width_out = ce_width;
763 if (child_width == 1) {
764 res = evaluate(_solver, metaSMT::logic::Ite(child, bvMinusOne(ce_width),
768 res = evaluate(_solver, sign_extend(ce_width - child_width, child));
775 AddExpr *ae = cast<AddExpr>(e);
777 res = evaluate(_solver, bvadd(construct(ae->left, width_out),
778 construct(ae->right, width_out)));
779 assert(*width_out != 1 &&
"uncanonicalized add");
784 SubExpr *se = cast<SubExpr>(e);
786 res = evaluate(_solver, bvsub(construct(se->left, width_out),
787 construct(se->right, width_out)));
788 assert(*width_out != 1 &&
"uncanonicalized sub");
793 MulExpr *me = cast<MulExpr>(e);
796 typename SolverContext::result_type right_expr =
797 evaluate(_solver, construct(me->right, width_out));
798 assert(*width_out != 1 &&
"uncanonicalized mul");
800 ConstantExpr *CE = dyn_cast<ConstantExpr>(me->left);
801 if (CE && (CE->getWidth() <= 64)) {
802 res = constructMulByConstant(right_expr, *width_out, CE->getZExtValue());
805 evaluate(_solver, bvmul(construct(me->left, width_out), right_expr));
811 UDivExpr *de = cast<UDivExpr>(e);
814 typename SolverContext::result_type left_expr =
815 construct(de->left, width_out);
816 assert(*width_out != 1 &&
"uncanonicalized udiv");
817 bool construct_both =
true;
819 ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right);
820 if (CE && (CE->getWidth() <= 64)) {
821 uint64_t divisor = CE->getZExtValue();
823 res = bvRightShift(left_expr, *width_out,
825 construct_both =
false;
826 }
else if (_optimizeDivides) {
827 if (*width_out == 32) {
829 constructUDivByConstant(left_expr, *width_out, (uint32_t)divisor);
830 construct_both =
false;
835 if (construct_both) {
837 evaluate(_solver, bvudiv(left_expr, construct(de->right, width_out)));
843 SDivExpr *de = cast<SDivExpr>(e);
846 typename SolverContext::result_type left_expr =
847 construct(de->left, width_out);
848 assert(*width_out != 1 &&
"uncanonicalized sdiv");
850 bool optimized =
false;
851 ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right);
852 if (CE && _optimizeDivides && (*width_out == 32)) {
853 llvm::APInt divisor = CE->getAPValue();
854 if (divisor != llvm::APInt(CE->getWidth(), 1,
false ) &&
855 divisor != llvm::APInt(CE->getWidth(), -1,
true )) {
856 res = constructSDivByConstant(left_expr, *width_out,
857 CE->getZExtValue(32));
863 evaluate(_solver, bvsdiv(left_expr, construct(de->right, width_out)));
869 URemExpr *de = cast<URemExpr>(e);
872 typename SolverContext::result_type left_expr =
873 construct(de->left, width_out);
874 assert(*width_out != 1 &&
"uncanonicalized urem");
876 bool construct_both =
true;
877 ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right);
878 if (CE && (CE->getWidth() <= 64)) {
880 uint64_t divisor = CE->getZExtValue();
887 res = bvZero(*width_out);
888 construct_both =
false;
890 res = evaluate(_solver, concat(bvZero(*width_out - bits),
891 bvExtract(left_expr, bits - 1, 0)));
892 construct_both =
false;
899 if (_optimizeDivides &&
901 typename SolverContext::result_type quotient =
902 constructUDivByConstant(left_expr, *width_out, (uint32_t)divisor);
903 typename SolverContext::result_type quot_times_divisor =
904 constructMulByConstant(quotient, *width_out, divisor);
905 res = evaluate(_solver, bvsub(left_expr, quot_times_divisor));
906 construct_both =
false;
910 if (construct_both) {
912 evaluate(_solver, bvurem(left_expr, construct(de->right, width_out)));
918 SRemExpr *de = cast<SRemExpr>(e);
921 typename SolverContext::result_type left_expr =
922 evaluate(_solver, construct(de->left, width_out));
923 typename SolverContext::result_type right_expr =
924 evaluate(_solver, construct(de->right, width_out));
925 assert(*width_out != 1 &&
"uncanonicalized srem");
927 bool construct_both =
true;
931 if (_optimizeDivides) {
932 if (ConstantExpr *cre = de->right->asConstant()) {
933 uint64_t divisor = cre->asUInt64;
936 if( *width_out == 32 ) {
937 typename SolverContext::result_type quotient = constructSDivByConstant(left, *width_out, divisor);
938 typename SolverContext::result_type quot_times_divisor = constructMulByConstant(quotient, *width_out, divisor);
939 res = vc_bvMinusExpr( vc, *width_out, left, quot_times_divisor );
940 construct_both =
false;
947 if (construct_both) {
948 res = evaluate(_solver, bvsrem(left_expr, right_expr));
954 NotExpr *
ne = cast<NotExpr>(e);
957 typename SolverContext::result_type child =
958 evaluate(_solver, construct(
ne->expr, width_out));
959 if (*width_out == 1) {
960 res = evaluate(_solver, metaSMT::logic::Not(child));
962 res = evaluate(_solver, bvnot(child));
968 AndExpr *ae = cast<AndExpr>(e);
971 typename SolverContext::result_type left_expr =
972 evaluate(_solver, construct(ae->left, width_out));
973 typename SolverContext::result_type right_expr =
974 evaluate(_solver, construct(ae->right, width_out));
976 if (*width_out == 1) {
977 res = evaluate(_solver, metaSMT::logic::And(left_expr, right_expr));
979 res = evaluate(_solver, bvand(left_expr, right_expr));
986 OrExpr *oe = cast<OrExpr>(e);
989 typename SolverContext::result_type left_expr =
990 evaluate(_solver, construct(oe->left, width_out));
991 typename SolverContext::result_type right_expr =
992 evaluate(_solver, construct(oe->right, width_out));
994 if (*width_out == 1) {
995 res = evaluate(_solver, metaSMT::logic::Or(left_expr, right_expr));
997 res = evaluate(_solver, bvor(left_expr, right_expr));
1004 XorExpr *xe = cast<XorExpr>(e);
1007 typename SolverContext::result_type left_expr =
1008 evaluate(_solver, construct(xe->left, width_out));
1009 typename SolverContext::result_type right_expr =
1010 evaluate(_solver, construct(xe->right, width_out));
1012 if (*width_out == 1) {
1013 res = evaluate(_solver, metaSMT::logic::Xor(left_expr, right_expr));
1015 res = evaluate(_solver, bvxor(left_expr, right_expr));
1022 ShlExpr *se = cast<ShlExpr>(e);
1025 typename SolverContext::result_type left_expr =
1026 evaluate(_solver, construct(se->left, width_out));
1027 assert(*width_out != 1 &&
"uncanonicalized shl");
1029 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(se->right)) {
1030 res = bvLeftShift(left_expr, *width_out, (
unsigned)CE->getLimitedValue());
1033 typename SolverContext::result_type right_expr =
1034 evaluate(_solver, construct(se->right, &shiftWidth));
1035 res = bvVarLeftShift(left_expr, right_expr, *width_out);
1042 LShrExpr *lse = cast<LShrExpr>(e);
1045 typename SolverContext::result_type left_expr =
1046 evaluate(_solver, construct(lse->left, width_out));
1047 assert(*width_out != 1 &&
"uncanonicalized lshr");
1049 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(lse->right)) {
1051 bvRightShift(left_expr, *width_out, (
unsigned)CE->getLimitedValue());
1054 typename SolverContext::result_type right_expr =
1055 evaluate(_solver, construct(lse->right, &shiftWidth));
1056 res = bvVarRightShift(left_expr, right_expr, *width_out);
1063 AShrExpr *ase = cast<AShrExpr>(e);
1066 typename SolverContext::result_type left_expr =
1067 evaluate(_solver, construct(ase->left, width_out));
1068 assert(*width_out != 1 &&
"uncanonicalized ashr");
1070 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(ase->right)) {
1071 unsigned shift = (unsigned)CE->getLimitedValue();
1072 typename SolverContext::result_type signedBool =
1073 bvBoolExtract(left_expr, *width_out - 1);
1074 res = constructAShrByConstant(left_expr, *width_out, shift, signedBool);
1077 typename SolverContext::result_type right_expr =
1078 evaluate(_solver, construct(ase->right, &shiftWidth));
1079 res = bvVarArithRightShift(left_expr, right_expr, *width_out);
1086 EqExpr *ee = cast<EqExpr>(e);
1089 typename SolverContext::result_type left_expr =
1090 evaluate(_solver, construct(ee->left, width_out));
1091 typename SolverContext::result_type right_expr =
1092 evaluate(_solver, construct(ee->right, width_out));
1094 if (*width_out == 1) {
1095 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(ee->left)) {
1099 res = evaluate(_solver, metaSMT::logic::Not(right_expr));
1102 res = evaluate(_solver, metaSMT::logic::equal(left_expr, right_expr));
1107 res = evaluate(_solver, metaSMT::logic::equal(left_expr, right_expr));
1114 UltExpr *ue = cast<UltExpr>(e);
1117 typename SolverContext::result_type left_expr =
1118 evaluate(_solver, construct(ue->left, width_out));
1119 typename SolverContext::result_type right_expr =
1120 evaluate(_solver, construct(ue->right, width_out));
1122 assert(*width_out != 1 &&
"uncanonicalized ult");
1125 res = evaluate(_solver, bvult(left_expr, right_expr));
1130 UleExpr *ue = cast<UleExpr>(e);
1133 typename SolverContext::result_type left_expr =
1134 evaluate(_solver, construct(ue->left, width_out));
1135 typename SolverContext::result_type right_expr =
1136 evaluate(_solver, construct(ue->right, width_out));
1138 assert(*width_out != 1 &&
"uncanonicalized ule");
1141 res = evaluate(_solver, bvule(left_expr, right_expr));
1146 SltExpr *se = cast<SltExpr>(e);
1149 typename SolverContext::result_type left_expr =
1150 evaluate(_solver, construct(se->left, width_out));
1151 typename SolverContext::result_type right_expr =
1152 evaluate(_solver, construct(se->right, width_out));
1154 assert(*width_out != 1 &&
"uncanonicalized slt");
1157 res = evaluate(_solver, bvslt(left_expr, right_expr));
1162 SleExpr *se = cast<SleExpr>(e);
1165 typename SolverContext::result_type left_expr =
1166 evaluate(_solver, construct(se->left, width_out));
1167 typename SolverContext::result_type right_expr =
1168 evaluate(_solver, construct(se->right, width_out));
1170 assert(*width_out != 1 &&
"uncanonicalized sle");
1173 res = evaluate(_solver, bvsle(left_expr, right_expr));
#define add(name, handler, ret)
static ref< ConstantExpr > alloc(const llvm::APInt &v)
@ Sge
Not used in canonical form.
@ Ne
Not used in canonical form.
@ Ugt
Not used in canonical form.
@ Sgt
Not used in canonical form.
@ Uge
Not used in canonical form.
uint64_t truncateToNBits(uint64_t x, unsigned N)
unsigned indexOfSingleBit(uint64_t x)
uint64_t isPowerOfTwo(uint64_t x)
uint64_t sub(uint64_t l, uint64_t r, unsigned inWidth)
uint64_t ne(uint64_t l, uint64_t r, unsigned inWidth)
Statistic queryConstructs
void ComputeMultConstants64(uint64_t multiplicand, uint64_t &add, uint64_t &sub)
void ComputeUDivConstants32(uint32_t d, uint32_t &mprime, uint32_t &sh1, uint32_t &sh2)
void ComputeSDivConstants32(int32_t d, int32_t &mprime, int32_t &dsign, int32_t &shpost)