1 /********************* */
2 /*! \file theory_bv_rewrite_rules_simplification.h
4 ** Top contributors (to current version):
5 ** Liana Hadarean, Aina Niemetz, Mathias Preiner
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
8 ** in the top-level source directory and their institutional affiliations.
9 ** All rights reserved. See the file COPYING in the top-level source
10 ** directory for licensing information.\endverbatim
12 ** \brief [[ Add one-line brief description here ]]
14 ** [[ Add lengthier description here ]]
15 ** \todo document this file
18 #include "cvc4_private.h"
22 #include "options/bv_options.h"
23 #include "theory/bv/theory_bv_rewrite_rules.h"
24 #include "theory/bv/theory_bv_utils.h"
25 #include "theory/rewriter.h"
31 /* -------------------------------------------------------------------------- */
37 inline bool RewriteRule
<BitOfConst
>::applies(TNode node
)
39 return node
.getKind() == kind::BITVECTOR_BITOF
&& node
[0].isConst();
43 inline Node RewriteRule
<BitOfConst
>::apply(TNode node
)
45 size_t pos
= node
.getOperator().getConst
<BitVectorBitOf
>().d_bitIndex
;
46 return utils::getBit(node
[0], pos
) ? utils::mkTrue() : utils::mkFalse();
49 /* -------------------------------------------------------------------------- */
54 * BITVECTOR_ITE with constant condition
57 inline bool RewriteRule
<BvIteConstCond
>::applies(TNode node
)
59 return (node
.getKind() == kind::BITVECTOR_ITE
&& node
[0].isConst());
63 inline Node RewriteRule
<BvIteConstCond
>::apply(TNode node
)
65 Debug("bv-rewrite") << "RewriteRule<BvIteConstCond>(" << node
<< ")"
67 return utils::isZero(node
[0]) ? node
[2] : node
[1];
70 /* -------------------------------------------------------------------------- */
75 * BITVECTOR_ITE with term_then = term_else
78 inline bool RewriteRule
<BvIteEqualChildren
>::applies(TNode node
)
80 return (node
.getKind() == kind::BITVECTOR_ITE
&& node
[1] == node
[2]);
84 inline Node RewriteRule
<BvIteEqualChildren
>::apply(TNode node
)
86 Debug("bv-rewrite") << "RewriteRule<BvIteEqualChildren>(" << node
<< ")"
91 /* -------------------------------------------------------------------------- */
96 * BITVECTOR_ITE with constant children of size one
99 inline bool RewriteRule
<BvIteConstChildren
>::applies(TNode node
)
101 return (node
.getKind() == kind::BITVECTOR_ITE
102 && utils::getSize(node
[1]) == 1
103 && node
[1].isConst() && node
[2].isConst());
107 inline Node RewriteRule
<BvIteConstChildren
>::apply(TNode node
)
109 Debug("bv-rewrite") << "RewriteRule<BvIteConstChildren>(" << node
<< ")"
111 if (utils::isOne(node
[1]) && utils::isZero(node
[2]))
115 Assert(utils::isZero(node
[1]) && utils::isOne(node
[2]));
116 return NodeManager::currentNM()->mkNode(kind::BITVECTOR_NOT
, node
[0]);
119 /* -------------------------------------------------------------------------- */
124 * Nested BITVECTOR_ITE with cond_outer == cond_inner
126 * c0 ? (c0 ? t0 : e0) : e1 -> c0 ? t0 : e1
127 * c0 ? t0 : (c0 ? t1 : e1) -> c0 ? t0 : e1
128 * c0 ? (c0 ? t0 : e0) : (c0 ? t1 : e1) -> c0 ? t0 : e1
131 inline bool RewriteRule
<BvIteEqualCond
>::applies(TNode node
)
134 node
.getKind() == kind::BITVECTOR_ITE
135 && ((node
[1].getKind() == kind::BITVECTOR_ITE
&& node
[0] == node
[1][0])
136 || (node
[2].getKind() == kind::BITVECTOR_ITE
137 && node
[0] == node
[2][0])));
141 inline Node RewriteRule
<BvIteEqualCond
>::apply(TNode node
)
143 Debug("bv-rewrite") << "RewriteRule<BvIteEqualCond>(" << node
<< ")"
145 Node t0
= node
[1].getKind() == kind::BITVECTOR_ITE
&& node
[0] == node
[1][0]
148 Node e1
= node
[2].getKind() == kind::BITVECTOR_ITE
&& node
[0] == node
[2][0]
151 return NodeManager::currentNM()->mkNode(kind::BITVECTOR_ITE
, node
[0], t0
, e1
);
154 /* -------------------------------------------------------------------------- */
159 * Nested BITVECTOR_ITE of the form
160 * c0 ? (c1 ? t1 : e1) : t1 -> c0 AND NOT(c1) ? e1 : t1
163 inline bool RewriteRule
<BvIteMergeThenIf
>::applies(TNode node
)
165 return (node
.getKind() == kind::BITVECTOR_ITE
166 && node
[1].getKind() == kind::BITVECTOR_ITE
167 && node
[1][1] == node
[2]);
171 inline Node RewriteRule
<BvIteMergeThenIf
>::apply(TNode node
)
173 Debug("bv-rewrite") << "RewriteRule<BvIteMergeThenIf>(" << node
<< ")"
175 NodeManager
* nm
= NodeManager::currentNM();
176 Assert(node
[1].getKind() == kind::BITVECTOR_ITE
);
177 Node cond
= nm
->mkNode(kind::BITVECTOR_AND
,
179 nm
->mkNode(kind::BITVECTOR_NOT
, node
[1][0]));
180 return nm
->mkNode(kind::BITVECTOR_ITE
, cond
, node
[1][2], node
[2]);
183 /* -------------------------------------------------------------------------- */
188 * Nested BITVECTOR_ITE of the form
189 * c0 ? (c1 ? t1 : e1) : e1 -> c0 AND c1 ? t1 : e1
192 inline bool RewriteRule
<BvIteMergeElseIf
>::applies(TNode node
)
194 return (node
.getKind() == kind::BITVECTOR_ITE
195 && node
[1].getKind() == kind::BITVECTOR_ITE
196 && node
[1][2] == node
[2]);
200 inline Node RewriteRule
<BvIteMergeElseIf
>::apply(TNode node
)
202 Debug("bv-rewrite") << "RewriteRule<BvIteMergeElseIf>(" << node
<< ")"
204 NodeManager
* nm
= NodeManager::currentNM();
205 Assert(node
[1].getKind() == kind::BITVECTOR_ITE
);
206 Node cond
= nm
->mkNode(kind::BITVECTOR_AND
, node
[0], node
[1][0]);
207 return nm
->mkNode(kind::BITVECTOR_ITE
, cond
, node
[1][1], node
[2]);
210 /* -------------------------------------------------------------------------- */
215 * Nested BITVECTOR_ITE of the form
216 * c0 ? t0 : (c1 ? t0 : e1) -> NOT(c0) AND NOT(c1) ? e1 : t0
219 inline bool RewriteRule
<BvIteMergeThenElse
>::applies(TNode node
)
221 return (node
.getKind() == kind::BITVECTOR_ITE
222 && node
[2].getKind() == kind::BITVECTOR_ITE
223 && node
[1] == node
[2][1]);
227 inline Node RewriteRule
<BvIteMergeThenElse
>::apply(TNode node
)
229 Debug("bv-rewrite") << "RewriteRule<BvIteMergeThenElse>(" << node
<< ")"
231 NodeManager
* nm
= NodeManager::currentNM();
232 Assert(node
[2].getKind() == kind::BITVECTOR_ITE
);
233 Node cond
= nm
->mkNode(kind::BITVECTOR_AND
,
234 nm
->mkNode(kind::BITVECTOR_NOT
, node
[0]),
235 nm
->mkNode(kind::BITVECTOR_NOT
, node
[2][0]));
236 return nm
->mkNode(kind::BITVECTOR_ITE
, cond
, node
[2][2], node
[1]);
239 /* -------------------------------------------------------------------------- */
244 * Nested BITVECTOR_ITE of the form
245 * c0 ? t0 : (c1 ? t1 : t0) -> NOT(c0) AND c1 ? t1 : t0
248 inline bool RewriteRule
<BvIteMergeElseElse
>::applies(TNode node
)
250 return (node
.getKind() == kind::BITVECTOR_ITE
251 && node
[2].getKind() == kind::BITVECTOR_ITE
252 && node
[1] == node
[2][2]);
256 inline Node RewriteRule
<BvIteMergeElseElse
>::apply(TNode node
)
258 Debug("bv-rewrite") << "RewriteRule<BvIteMergeElseElse>(" << node
<< ")"
260 NodeManager
* nm
= NodeManager::currentNM();
261 Assert(node
[2].getKind() == kind::BITVECTOR_ITE
);
262 Node cond
= nm
->mkNode(kind::BITVECTOR_AND
,
263 nm
->mkNode(kind::BITVECTOR_NOT
, node
[0]),
265 return nm
->mkNode(kind::BITVECTOR_ITE
, cond
, node
[2][1], node
[1]);
268 /* -------------------------------------------------------------------------- */
273 * BITVECTOR_COMP of children of size 1 with one constant child
276 inline bool RewriteRule
<BvComp
>::applies(TNode node
)
278 return (node
.getKind() == kind::BITVECTOR_COMP
279 && utils::getSize(node
[0]) == 1
280 && (node
[0].isConst() || node
[1].isConst()));
284 inline Node RewriteRule
<BvComp
>::apply(TNode node
)
286 Debug("bv-rewrite") << "RewriteRule<BvComp>(" << node
<< ")" << std::endl
;
287 NodeManager
* nm
= NodeManager::currentNM();
288 if (node
[0].isConst())
290 return utils::isZero(node
[0]) ? nm
->mkNode(kind::BITVECTOR_NOT
, node
[1])
293 return utils::isZero(node
[1]) ? nm
->mkNode(kind::BITVECTOR_NOT
, node
[0])
297 /* -------------------------------------------------------------------------- */
302 * Left Shift by constant amount
305 bool RewriteRule
<ShlByConst
>::applies(TNode node
) {
306 // if the shift amount is constant
307 return (node
.getKind() == kind::BITVECTOR_SHL
&&
308 node
[1].getKind() == kind::CONST_BITVECTOR
);
312 Node RewriteRule
<ShlByConst
>::apply(TNode node
) {
313 Debug("bv-rewrite") << "RewriteRule<ShlByConst>(" << node
<< ")" << std::endl
;
314 Integer amount
= node
[1].getConst
<BitVector
>().toInteger();
319 uint32_t size
= utils::getSize(a
);
322 if (amount
>= Integer(size
)) {
323 // if we are shifting more than the length of the bitvector return 0
324 return utils::mkZero(size
);
327 // make sure we do not lose information casting
328 Assert(amount
< Integer(1).multiplyByPow2(32));
330 uint32_t uint32_amount
= amount
.toUnsignedInt();
332 Node left
= utils::mkExtract(a
, size
- 1 - uint32_amount
, 0);
333 Node right
= utils::mkZero(uint32_amount
);
334 return utils::mkConcat(left
, right
);
337 /* -------------------------------------------------------------------------- */
342 * Right Logical Shift by constant amount
346 bool RewriteRule
<LshrByConst
>::applies(TNode node
) {
347 // if the shift amount is constant
348 return (node
.getKind() == kind::BITVECTOR_LSHR
&&
349 node
[1].getKind() == kind::CONST_BITVECTOR
);
353 Node RewriteRule
<LshrByConst
>::apply(TNode node
) {
354 Debug("bv-rewrite") << "RewriteRule<LshrByConst>(" << node
<< ")" << std::endl
;
355 Integer amount
= node
[1].getConst
<BitVector
>().toInteger();
361 uint32_t size
= utils::getSize(a
);
364 if (amount
>= Integer(size
)) {
365 // if we are shifting more than the length of the bitvector return 0
366 return utils::mkZero(size
);
369 // make sure we do not lose information casting
370 Assert(amount
< Integer(1).multiplyByPow2(32));
372 uint32_t uint32_amount
= amount
.toUnsignedInt();
373 Node right
= utils::mkExtract(a
, size
- 1, uint32_amount
);
374 Node left
= utils::mkZero(uint32_amount
);
375 return utils::mkConcat(left
, right
);
378 /* -------------------------------------------------------------------------- */
383 * Right Arithmetic Shift by constant amount
387 bool RewriteRule
<AshrByConst
>::applies(TNode node
) {
388 // if the shift amount is constant
389 return (node
.getKind() == kind::BITVECTOR_ASHR
&&
390 node
[1].getKind() == kind::CONST_BITVECTOR
);
394 Node RewriteRule
<AshrByConst
>::apply(TNode node
) {
395 Debug("bv-rewrite") << "RewriteRule<AshrByConst>(" << node
<< ")" << std::endl
;
396 Integer amount
= node
[1].getConst
<BitVector
>().toInteger();
402 uint32_t size
= utils::getSize(a
);
403 Node sign_bit
= utils::mkExtract(a
, size
-1, size
-1);
405 if (amount
>= Integer(size
)) {
406 // if we are shifting more than the length of the bitvector return n repetitions
408 return utils::mkConcat(sign_bit
, size
);
411 // make sure we do not lose information casting
412 Assert(amount
< Integer(1).multiplyByPow2(32));
414 uint32_t uint32_amount
= amount
.toUnsignedInt();
415 if (uint32_amount
== 0) {
419 Node left
= utils::mkConcat(sign_bit
, uint32_amount
);
420 Node right
= utils::mkExtract(a
, size
- 1, uint32_amount
);
421 return utils::mkConcat(left
, right
);
424 /* -------------------------------------------------------------------------- */
434 bool RewriteRule
<BitwiseIdemp
>::applies(TNode node
) {
436 return ((node
.getKind() == kind::BITVECTOR_AND
||
437 node
.getKind() == kind::BITVECTOR_OR
) &&
438 node
.getNumChildren() == 2 &&
443 Node RewriteRule
<BitwiseIdemp
>::apply(TNode node
) {
445 Debug("bv-rewrite") << "RewriteRule<BitwiseIdemp>(" << node
<< ")" << std::endl
;
449 /* -------------------------------------------------------------------------- */
458 bool RewriteRule
<AndZero
>::applies(TNode node
) {
460 unsigned size
= utils::getSize(node
);
461 return (node
.getKind() == kind::BITVECTOR_AND
&&
462 node
.getNumChildren() == 2 &&
463 (node
[0] == utils::mkConst(size
, 0) ||
464 node
[1] == utils::mkConst(size
, 0)));
468 Node RewriteRule
<AndZero
>::apply(TNode node
) {
470 Debug("bv-rewrite") << "RewriteRule<AndZero>(" << node
<< ")" << std::endl
;
471 return utils::mkConst(utils::getSize(node
), 0);
474 /* -------------------------------------------------------------------------- */
483 bool RewriteRule
<AndOne
>::applies(TNode node
) {
485 unsigned size
= utils::getSize(node
);
486 Node ones
= utils::mkOnes(size
);
487 return (node
.getKind() == kind::BITVECTOR_AND
&&
488 node
.getNumChildren() == 2 &&
494 Node RewriteRule
<AndOne
>::apply(TNode node
) {
496 Debug("bv-rewrite") << "RewriteRule<AndOne>(" << node
<< ")" << std::endl
;
497 unsigned size
= utils::getSize(node
);
499 if (node
[0] == utils::mkOnes(size
)) {
502 Assert(node
[1] == utils::mkOnes(size
));
507 /* -------------------------------------------------------------------------- */
510 * AndOrXorConcatPullUp
512 * Match: x_m <op> concat(y_my, <const>_n, z_mz)
513 * <const>_n in { 0_n, 1_n, ~0_n }
515 * Rewrites to: concat(x[m-1:m-my] <op> y,
516 * x[m-my-1:mz] <op> <const>_n,
521 inline bool RewriteRule
<AndOrXorConcatPullUp
>::applies(TNode node
)
523 if (node
.getKind() != kind::BITVECTOR_AND
524 && node
.getKind() != kind::BITVECTOR_OR
525 && node
.getKind() != kind::BITVECTOR_XOR
)
532 for (const TNode
& c
: node
)
534 if (c
.getKind() == kind::BITVECTOR_CONCAT
)
536 for (const TNode
& cc
: c
)
547 if (n
.isNull()) return false;
548 return utils::isZero(n
) || utils::isOne(n
) || utils::isOnes(n
);
552 inline Node RewriteRule
<AndOrXorConcatPullUp
>::apply(TNode node
)
554 Debug("bv-rewrite") << "RewriteRule<AndOrXorConcatPullUp>(" << node
<< ")"
558 Kind kind
= node
.getKind();
561 NodeBuilder
<> xb(kind
);
562 NodeBuilder
<> yb(kind::BITVECTOR_CONCAT
);
563 NodeBuilder
<> zb(kind::BITVECTOR_CONCAT
);
564 NodeBuilder
<> res(kind::BITVECTOR_CONCAT
);
565 NodeManager
* nm
= NodeManager::currentNM();
567 for (const TNode
& child
: node
)
569 if (concat
.isNull() && child
.getKind() == kind::BITVECTOR_CONCAT
)
578 x
= xb
.getNumChildren() > 1 ? xb
.constructNode() : xb
[0];
580 for (const TNode
& child
: concat
)
584 if (utils::isZero(child
) || utils::isOne(child
) || utils::isOnes(child
))
599 Assert(yb
.getNumChildren() || zb
.getNumChildren());
601 if ((nc
= yb
.getNumChildren()) > 0)
603 y
= nc
> 1 ? yb
.constructNode() : yb
[0];
605 if ((nc
= zb
.getNumChildren()) > 0)
607 z
= nc
> 1 ? zb
.constructNode() : zb
[0];
609 m
= utils::getSize(x
);
610 #ifdef CVC4_ASSERTIONS
611 uint32_t n
= utils::getSize(c
);
613 my
= y
.isNull() ? 0 : utils::getSize(y
);
614 mz
= z
.isNull() ? 0 : utils::getSize(z
);
615 Assert(mz
== m
- my
- n
);
620 res
<< nm
->mkNode(kind
, utils::mkExtract(x
, m
- 1, m
- my
), y
);
623 res
<< nm
->mkNode(kind
, utils::mkExtract(x
, m
- my
- 1, mz
), c
);
627 res
<< nm
->mkNode(kind
, utils::mkExtract(x
, mz
- 1, 0), z
);
633 /* -------------------------------------------------------------------------- */
642 bool RewriteRule
<OrZero
>::applies(TNode node
) {
644 unsigned size
= utils::getSize(node
);
645 return (node
.getKind() == kind::BITVECTOR_OR
&&
646 node
.getNumChildren() == 2 &&
647 (node
[0] == utils::mkConst(size
, 0) ||
648 node
[1] == utils::mkConst(size
, 0)));
652 Node RewriteRule
<OrZero
>::apply(TNode node
) {
654 Debug("bv-rewrite") << "RewriteRule<OrZero>(" << node
<< ")" << std::endl
;
656 unsigned size
= utils::getSize(node
);
657 if (node
[0] == utils::mkConst(size
, 0)) {
660 Assert(node
[1] == utils::mkConst(size
, 0));
665 /* -------------------------------------------------------------------------- */
674 bool RewriteRule
<OrOne
>::applies(TNode node
) {
676 unsigned size
= utils::getSize(node
);
677 Node ones
= utils::mkOnes(size
);
678 return (node
.getKind() == kind::BITVECTOR_OR
&&
679 node
.getNumChildren() == 2 &&
685 Node RewriteRule
<OrOne
>::apply(TNode node
) {
687 Debug("bv-rewrite") << "RewriteRule<OrOne>(" << node
<< ")" << std::endl
;
688 return utils::mkOnes(utils::getSize(node
));
691 /* -------------------------------------------------------------------------- */
700 bool RewriteRule
<XorDuplicate
>::applies(TNode node
) {
702 return (node
.getKind() == kind::BITVECTOR_XOR
&&
703 node
.getNumChildren() == 2 &&
708 Node RewriteRule
<XorDuplicate
>::apply(TNode node
) {
710 Debug("bv-rewrite") << "RewriteRule<XorDuplicate>(" << node
<< ")" << std::endl
;
711 return utils::mkZero(utils::getSize(node
));
714 /* -------------------------------------------------------------------------- */
723 bool RewriteRule
<XorOne
>::applies(TNode node
) {
724 if (node
.getKind() != kind::BITVECTOR_XOR
) {
727 Node ones
= utils::mkOnes(utils::getSize(node
));
728 for (unsigned i
= 0; i
< node
.getNumChildren(); ++i
) {
729 if (node
[i
] == ones
) {
737 inline Node RewriteRule
<XorOne
>::apply(TNode node
)
739 Debug("bv-rewrite") << "RewriteRule<XorOne>(" << node
<< ")" << std::endl
;
740 NodeManager
*nm
= NodeManager::currentNM();
741 Node ones
= utils::mkOnes(utils::getSize(node
));
742 std::vector
<Node
> children
;
743 bool found_ones
= false;
744 // XorSimplify should have been called before
745 for (unsigned i
= 0; i
< node
.getNumChildren(); ++i
)
749 // make sure only ones occurs only once
750 found_ones
= !found_ones
;
754 children
.push_back(node
[i
]);
758 Node result
= utils::mkNaryNode(kind::BITVECTOR_XOR
, children
);
761 result
= nm
->mkNode(kind::BITVECTOR_NOT
, result
);
766 /* -------------------------------------------------------------------------- */
775 bool RewriteRule
<XorZero
>::applies(TNode node
) {
776 if (node
.getKind() != kind::BITVECTOR_XOR
) {
779 Node zero
= utils::mkConst(utils::getSize(node
), 0);
780 for (unsigned i
= 0; i
< node
.getNumChildren(); ++i
) {
781 if (node
[i
] == zero
) {
789 inline Node RewriteRule
<XorZero
>::apply(TNode node
)
791 Debug("bv-rewrite") << "RewriteRule<XorZero>(" << node
<< ")" << std::endl
;
792 std::vector
<Node
> children
;
793 Node zero
= utils::mkConst(utils::getSize(node
), 0);
795 // XorSimplify should have been called before
796 for (unsigned i
= 0; i
< node
.getNumChildren(); ++i
)
800 children
.push_back(node
[i
]);
803 Node res
= utils::mkNaryNode(kind::BITVECTOR_XOR
, children
);
807 /* -------------------------------------------------------------------------- */
812 * (a bvand (~ a)) ==> 0
816 bool RewriteRule
<BitwiseNotAnd
>::applies(TNode node
) {
818 return (node
.getKind() == kind::BITVECTOR_AND
&&
819 node
.getNumChildren() == 2 &&
820 ((node
[0].getKind() == kind::BITVECTOR_NOT
&& node
[0][0] == node
[1]) ||
821 (node
[1].getKind() == kind::BITVECTOR_NOT
&& node
[1][0] == node
[0])));
825 Node RewriteRule
<BitwiseNotAnd
>::apply(TNode node
) {
827 Debug("bv-rewrite") << "RewriteRule<BitwiseNegAnd>(" << node
<< ")" << std::endl
;
828 return utils::mkZero(utils::getSize(node
));
831 /* -------------------------------------------------------------------------- */
836 * (a bvor (~ a)) ==> 1
840 bool RewriteRule
<BitwiseNotOr
>::applies(TNode node
) {
842 return (node
.getKind() == kind::BITVECTOR_OR
&&
843 node
.getNumChildren() == 2 &&
844 ((node
[0].getKind() == kind::BITVECTOR_NOT
&& node
[0][0] == node
[1]) ||
845 (node
[1].getKind() == kind::BITVECTOR_NOT
&& node
[1][0] == node
[0])));
849 Node RewriteRule
<BitwiseNotOr
>::apply(TNode node
) {
851 Debug("bv-rewrite") << "RewriteRule<BitwiseNotOr>(" << node
<< ")" << std::endl
;
852 uint32_t size
= utils::getSize(node
);
853 return utils::mkOnes(size
);
856 /* -------------------------------------------------------------------------- */
861 * ((~ a) bvxor (~ b)) ==> (a bvxor b)
865 bool RewriteRule
<XorNot
>::applies(TNode node
) {
870 inline Node RewriteRule
<XorNot
>::apply(TNode node
)
873 Debug("bv-rewrite") << "RewriteRule<XorNot>(" << node
<< ")" << std::endl
;
876 return NodeManager::currentNM()->mkNode(kind::BITVECTOR_XOR
, a
, b
);
879 /* -------------------------------------------------------------------------- */
884 * ~(a bvxor b) ==> (~ a bvxor b)
888 bool RewriteRule
<NotXor
>::applies(TNode node
) {
889 return (node
.getKind() == kind::BITVECTOR_NOT
&&
890 node
[0].getKind() == kind::BITVECTOR_XOR
);
894 inline Node RewriteRule
<NotXor
>::apply(TNode node
)
896 Debug("bv-rewrite") << "RewriteRule<NotXor>(" << node
<< ")" << std::endl
;
897 std::vector
<Node
> children
;
898 TNode::iterator child_it
= node
[0].begin();
900 NodeManager::currentNM()->mkNode(kind::BITVECTOR_NOT
, *child_it
));
901 for (++child_it
; child_it
!= node
[0].end(); ++child_it
)
903 children
.push_back(*child_it
);
905 return utils::mkSortedNode(kind::BITVECTOR_XOR
, children
);
908 /* -------------------------------------------------------------------------- */
917 bool RewriteRule
<NotIdemp
>::applies(TNode node
) {
918 return (node
.getKind() == kind::BITVECTOR_NOT
&&
919 node
[0].getKind() == kind::BITVECTOR_NOT
);
923 Node RewriteRule
<NotIdemp
>::apply(TNode node
) {
924 Debug("bv-rewrite") << "RewriteRule<NotIdemp>(" << node
<< ")" << std::endl
;
928 /* -------------------------------------------------------------------------- */
937 bool RewriteRule
<LtSelf
>::applies(TNode node
) {
938 return ((node
.getKind() == kind::BITVECTOR_ULT
||
939 node
.getKind() == kind::BITVECTOR_SLT
) &&
944 Node RewriteRule
<LtSelf
>::apply(TNode node
) {
945 Debug("bv-rewrite") << "RewriteRule<LtSelf>(" << node
<< ")" << std::endl
;
946 return utils::mkFalse();
949 /* -------------------------------------------------------------------------- */
958 bool RewriteRule
<LteSelf
>::applies(TNode node
) {
959 return ((node
.getKind() == kind::BITVECTOR_ULE
||
960 node
.getKind() == kind::BITVECTOR_SLE
) &&
965 Node RewriteRule
<LteSelf
>::apply(TNode node
) {
966 Debug("bv-rewrite") << "RewriteRule<LteSelf>(" << node
<< ")" << std::endl
;
967 return utils::mkTrue();
970 /* -------------------------------------------------------------------------- */
979 inline bool RewriteRule
<ZeroUlt
>::applies(TNode node
)
981 return (node
.getKind() == kind::BITVECTOR_ULT
982 && node
[0] == utils::mkZero(utils::getSize(node
[0])));
986 inline Node RewriteRule
<ZeroUlt
>::apply(TNode node
)
988 Debug("bv-rewrite") << "RewriteRule<ZeroUlt>(" << node
<< ")" << std::endl
;
989 NodeManager
*nm
= NodeManager::currentNM();
990 return nm
->mkNode(kind::NOT
, nm
->mkNode(kind::EQUAL
, node
[0], node
[1]));
993 /* -------------------------------------------------------------------------- */
1002 bool RewriteRule
<UltZero
>::applies(TNode node
) {
1003 return (node
.getKind() == kind::BITVECTOR_ULT
&&
1004 node
[1] == utils::mkZero(utils::getSize(node
[0])));
1008 Node RewriteRule
<UltZero
>::apply(TNode node
) {
1009 Debug("bv-rewrite") << "RewriteRule<UltZero>(" << node
<< ")" << std::endl
;
1010 return utils::mkFalse();
1014 /* -------------------------------------------------------------------------- */
1020 bool RewriteRule
<UltOne
>::applies(TNode node
) {
1021 return (node
.getKind() == kind::BITVECTOR_ULT
&&
1022 node
[1] == utils::mkOne(utils::getSize(node
[0])));
1026 inline Node RewriteRule
<UltOne
>::apply(TNode node
)
1028 Debug("bv-rewrite") << "RewriteRule<UltOne>(" << node
<< ")" << std::endl
;
1029 return NodeManager::currentNM()->mkNode(
1030 kind::EQUAL
, node
[0], utils::mkZero(utils::getSize(node
[0])));
1033 /* -------------------------------------------------------------------------- */
1039 bool RewriteRule
<SltZero
>::applies(TNode node
) {
1040 return (node
.getKind() == kind::BITVECTOR_SLT
&&
1041 node
[1] == utils::mkZero(utils::getSize(node
[0])));
1045 inline Node RewriteRule
<SltZero
>::apply(TNode node
)
1047 Debug("bv-rewrite") << "RewriteRule<UltZero>(" << node
<< ")" << std::endl
;
1048 unsigned size
= utils::getSize(node
[0]);
1049 Node most_significant_bit
= utils::mkExtract(node
[0], size
- 1, size
- 1);
1050 return NodeManager::currentNM()->mkNode(
1051 kind::EQUAL
, most_significant_bit
, utils::mkOne(1));
1054 /* -------------------------------------------------------------------------- */
1063 bool RewriteRule
<UltSelf
>::applies(TNode node
) {
1064 return (node
.getKind() == kind::BITVECTOR_ULT
&&
1065 node
[1] == node
[0]);
1069 Node RewriteRule
<UltSelf
>::apply(TNode node
) {
1070 Debug("bv-rewrite") << "RewriteRule<UltSelf>(" << node
<< ")" << std::endl
;
1071 return utils::mkFalse();
1075 /* -------------------------------------------------------------------------- */
1084 bool RewriteRule
<UleZero
>::applies(TNode node
) {
1085 return (node
.getKind() == kind::BITVECTOR_ULE
&&
1086 node
[1] == utils::mkZero(utils::getSize(node
[0])));
1090 inline Node RewriteRule
<UleZero
>::apply(TNode node
)
1092 Debug("bv-rewrite") << "RewriteRule<UleZero>(" << node
<< ")" << std::endl
;
1093 return NodeManager::currentNM()->mkNode(kind::EQUAL
, node
[0], node
[1]);
1096 /* -------------------------------------------------------------------------- */
1105 bool RewriteRule
<UleSelf
>::applies(TNode node
) {
1106 return (node
.getKind() == kind::BITVECTOR_ULE
&&
1107 node
[1] == node
[0]);
1111 Node RewriteRule
<UleSelf
>::apply(TNode node
) {
1112 Debug("bv-rewrite") << "RewriteRule<UleSelf>(" << node
<< ")" << std::endl
;
1113 return utils::mkTrue();
1116 /* -------------------------------------------------------------------------- */
1125 bool RewriteRule
<ZeroUle
>::applies(TNode node
) {
1126 return (node
.getKind() == kind::BITVECTOR_ULE
&&
1127 node
[0] == utils::mkZero(utils::getSize(node
[0])));
1131 Node RewriteRule
<ZeroUle
>::apply(TNode node
) {
1132 Debug("bv-rewrite") << "RewriteRule<ZeroUle>(" << node
<< ")" << std::endl
;
1133 return utils::mkTrue();
1136 /* -------------------------------------------------------------------------- */
1141 * a <= 11..1 ==> true
1145 bool RewriteRule
<UleMax
>::applies(TNode node
) {
1146 if (node
.getKind()!= kind::BITVECTOR_ULE
) {
1149 uint32_t size
= utils::getSize(node
[0]);
1150 return (node
.getKind() == kind::BITVECTOR_ULE
1151 && node
[1] == utils::mkOnes(size
));
1155 Node RewriteRule
<UleMax
>::apply(TNode node
) {
1156 Debug("bv-rewrite") << "RewriteRule<UleMax>(" << node
<< ")" << std::endl
;
1157 return utils::mkTrue();
1160 /* -------------------------------------------------------------------------- */
1165 * ~ ( a < b) ==> b <= a
1169 bool RewriteRule
<NotUlt
>::applies(TNode node
) {
1170 return (node
.getKind() == kind::NOT
&&
1171 node
[0].getKind() == kind::BITVECTOR_ULT
);
1175 inline Node RewriteRule
<NotUlt
>::apply(TNode node
)
1177 Debug("bv-rewrite") << "RewriteRule<NotUlt>(" << node
<< ")" << std::endl
;
1181 return NodeManager::currentNM()->mkNode(kind::BITVECTOR_ULE
, b
, a
);
1184 /* -------------------------------------------------------------------------- */
1189 * ~ ( a <= b) ==> b < a
1193 bool RewriteRule
<NotUle
>::applies(TNode node
) {
1194 return (node
.getKind() == kind::NOT
&&
1195 node
[0].getKind() == kind::BITVECTOR_ULE
);
1199 inline Node RewriteRule
<NotUle
>::apply(TNode node
)
1201 Debug("bv-rewrite") << "RewriteRule<NotUle>(" << node
<< ")" << std::endl
;
1205 return NodeManager::currentNM()->mkNode(kind::BITVECTOR_ULT
, b
, a
);
1208 /* -------------------------------------------------------------------------- */
1213 * (a * 2^k) ==> a[n-k-1:0] 0_k
1217 inline bool RewriteRule
<MultPow2
>::applies(TNode node
)
1219 if (node
.getKind() != kind::BITVECTOR_MULT
)
1222 for (const Node
& cn
: node
)
1224 bool cIsNeg
= false;
1225 if (utils::isPow2Const(cn
, cIsNeg
))
1234 inline Node RewriteRule
<MultPow2
>::apply(TNode node
)
1236 Debug("bv-rewrite") << "RewriteRule<MultPow2>(" << node
<< ")" << std::endl
;
1237 NodeManager
*nm
= NodeManager::currentNM();
1238 unsigned size
= utils::getSize(node
);
1239 std::vector
<Node
> children
;
1240 unsigned exponent
= 0;
1242 for (const Node
& cn
: node
)
1244 bool cIsNeg
= false;
1245 unsigned exp
= utils::isPow2Const(cn
, cIsNeg
);
1247 exponent
+= exp
- 1;
1254 children
.push_back(cn
);
1257 if (exponent
>= size
)
1259 return utils::mkZero(size
);
1263 if (children
.empty())
1265 a
= utils::mkOne(size
);
1269 a
= utils::mkNaryNode(kind::BITVECTOR_MULT
, children
);
1272 if (isNeg
&& size
> 1)
1274 a
= nm
->mkNode(kind::BITVECTOR_NEG
, a
);
1280 Node extract
= utils::mkExtract(a
, size
- exponent
- 1, 0);
1281 Node zeros
= utils::mkConst(exponent
, 0);
1282 return utils::mkConcat(extract
, zeros
);
1285 /* -------------------------------------------------------------------------- */
1288 * ExtractMultLeadingBit
1290 * If the bit-vectors multiplied have enough leading zeros,
1291 * we can determine that the top bits of the multiplication
1292 * are zero and not compute them. Only apply for large bitwidths
1293 * as this can interfere with other mult normalization rewrites such
1298 bool RewriteRule
<ExtractMultLeadingBit
>::applies(TNode node
) {
1299 if (node
.getKind() != kind::BITVECTOR_EXTRACT
)
1301 unsigned low
= utils::getExtractLow(node
);
1304 if (node
.getKind() != kind::BITVECTOR_MULT
||
1305 node
.getNumChildren() != 2 ||
1306 utils::getSize(node
) <= 64)
1309 if (node
[0].getKind() != kind::BITVECTOR_CONCAT
||
1310 node
[1].getKind() != kind::BITVECTOR_CONCAT
||
1311 !node
[0][0].isConst() ||
1312 !node
[1][0].isConst())
1315 unsigned n
= utils::getSize(node
);
1316 // count number of leading zeroes
1317 const Integer
& int1
= node
[0][0].getConst
<BitVector
>().toInteger();
1318 const Integer
& int2
= node
[1][0].getConst
<BitVector
>().toInteger();
1319 size_t int1_size
= utils::getSize(node
[0][0]);
1320 size_t int2_size
= utils::getSize(node
[1][0]);
1321 unsigned zeroes1
= int1
.isZero() ? int1_size
: int1_size
- int1
.length();
1322 unsigned zeroes2
= int2
.isZero() ? int2_size
: int2_size
- int2
.length();
1324 // first k bits are not zero in the result
1325 unsigned k
= 2 * n
- (zeroes1
+ zeroes2
);
1334 Node RewriteRule
<ExtractMultLeadingBit
>::apply(TNode node
) {
1335 Debug("bv-rewrite") << "RewriteRule<MultLeadingBit>(" << node
<< ")" << std::endl
;
1337 unsigned bitwidth
= utils::getSize(node
);
1340 // const Integer& int1 = node[0][0].getConst<BitVector>().toInteger();
1341 // const Integer& int2 = node[1][0].getConst<BitVector>().toInteger();
1342 // unsigned zeroes1 = int1.isZero()? utils::getSize(node[0][0]) :
1345 // unsigned zeroes2 = int2.isZero()? utils::getSize(node[1][0]) :
1347 // all bits >= k in the multiplier will have to be 0
1348 // unsigned n = utils::getSize(node);
1349 // unsigned k = 2 * n - (zeroes1 + zeroes2);
1350 // Node extract1 = utils::mkExtract(node[0], k - 1, 0);
1351 // Node extract2 = utils::mkExtract(node[1], k - 1, 0);
1352 // Node k_zeroes = utils::mkConst(n - k, 0u);
1354 // NodeManager *nm = NodeManager::currentNM();
1355 // Node new_mult = nm->mkNode(kind::BITVECTOR_MULT, extract1, extract2);
1356 // Node result = utils::mkExtract(nm->mkNode(kind::BITVECTOR_CONCAT, k_zeroes, new_mult), high, low);
1358 // since the extract is over multiplier bits that have to be 0, return 0
1359 Node result
= utils::mkConst(bitwidth
, 0u);
1360 // std::cout << "MultLeadingBit " << node <<" => " << result <<"\n";
1364 /* -------------------------------------------------------------------------- */
1373 bool RewriteRule
<NegIdemp
>::applies(TNode node
) {
1374 return (node
.getKind() == kind::BITVECTOR_NEG
&&
1375 node
[0].getKind() == kind::BITVECTOR_NEG
);
1379 Node RewriteRule
<NegIdemp
>::apply(TNode node
) {
1380 Debug("bv-rewrite") << "RewriteRule<NegIdemp>(" << node
<< ")" << std::endl
;
1384 /* -------------------------------------------------------------------------- */
1389 * (a udiv 2^k) ==> 0_k a[n-1: k]
1393 inline bool RewriteRule
<UdivPow2
>::applies(TNode node
)
1396 if (node
.getKind() == kind::BITVECTOR_UDIV_TOTAL
1397 && utils::isPow2Const(node
[1], isNeg
))
1405 inline Node RewriteRule
<UdivPow2
>::apply(TNode node
)
1407 Debug("bv-rewrite") << "RewriteRule<UdivPow2>(" << node
<< ")" << std::endl
;
1408 NodeManager
*nm
= NodeManager::currentNM();
1409 unsigned size
= utils::getSize(node
);
1412 unsigned power
= utils::isPow2Const(node
[1], isNeg
) - 1;
1420 Node extract
= utils::mkExtract(a
, size
- 1, power
);
1421 Node zeros
= utils::mkConst(power
, 0);
1423 ret
= nm
->mkNode(kind::BITVECTOR_CONCAT
, zeros
, extract
);
1425 if (isNeg
&& size
> 1)
1427 ret
= nm
->mkNode(kind::BITVECTOR_NEG
, ret
);
1432 /* -------------------------------------------------------------------------- */
1437 * (a udiv 0) ==> 111...1
1441 inline bool RewriteRule
<UdivZero
>::applies(TNode node
) {
1442 return (node
.getKind() == kind::BITVECTOR_UDIV_TOTAL
&&
1443 node
[1] == utils::mkConst(utils::getSize(node
), 0));
1447 inline Node RewriteRule
<UdivZero
>::apply(TNode node
) {
1448 Debug("bv-rewrite") << "RewriteRule<UdivZero>(" << node
<< ")" << std::endl
;
1449 return utils::mkOnes(utils::getSize(node
));
1452 /* -------------------------------------------------------------------------- */
1461 inline bool RewriteRule
<UdivOne
>::applies(TNode node
) {
1462 return (node
.getKind() == kind::BITVECTOR_UDIV_TOTAL
&&
1463 node
[1] == utils::mkConst(utils::getSize(node
), 1));
1467 inline Node RewriteRule
<UdivOne
>::apply(TNode node
) {
1468 Debug("bv-rewrite") << "RewriteRule<UdivOne>(" << node
<< ")" << std::endl
;
1472 /* -------------------------------------------------------------------------- */
1477 * (a urem 2^k) ==> 0_(n-k) a[k-1:0]
1481 inline bool RewriteRule
<UremPow2
>::applies(TNode node
)
1484 if (node
.getKind() == kind::BITVECTOR_UREM_TOTAL
1485 && utils::isPow2Const(node
[1], isNeg
))
1493 inline Node RewriteRule
<UremPow2
>::apply(TNode node
)
1495 Debug("bv-rewrite") << "RewriteRule<UremPow2>(" << node
<< ")" << std::endl
;
1498 unsigned power
= utils::isPow2Const(node
[1], isNeg
) - 1;
1502 ret
= utils::mkZero(utils::getSize(node
));
1506 Node extract
= utils::mkExtract(a
, power
- 1, 0);
1507 Node zeros
= utils::mkZero(utils::getSize(node
) - power
);
1508 ret
= NodeManager::currentNM()->mkNode(
1509 kind::BITVECTOR_CONCAT
, zeros
, extract
);
1514 /* -------------------------------------------------------------------------- */
1523 bool RewriteRule
<UremOne
>::applies(TNode node
) {
1524 return (node
.getKind() == kind::BITVECTOR_UREM_TOTAL
&&
1525 node
[1] == utils::mkConst(utils::getSize(node
), 1));
1529 Node RewriteRule
<UremOne
>::apply(TNode node
) {
1530 Debug("bv-rewrite") << "RewriteRule<UremOne>(" << node
<< ")" << std::endl
;
1531 return utils::mkConst(utils::getSize(node
), 0);
1534 /* -------------------------------------------------------------------------- */
1543 bool RewriteRule
<UremSelf
>::applies(TNode node
) {
1544 return (node
.getKind() == kind::BITVECTOR_UREM_TOTAL
&&
1545 node
[0] == node
[1]);
1549 Node RewriteRule
<UremSelf
>::apply(TNode node
) {
1550 Debug("bv-rewrite") << "RewriteRule<UremSelf>(" << node
<< ")" << std::endl
;
1551 return utils::mkConst(utils::getSize(node
), 0);
1554 /* -------------------------------------------------------------------------- */
1559 * (0_k >> a) ==> 0_k
1563 bool RewriteRule
<ShiftZero
>::applies(TNode node
) {
1564 return ((node
.getKind() == kind::BITVECTOR_SHL
||
1565 node
.getKind() == kind::BITVECTOR_LSHR
||
1566 node
.getKind() == kind::BITVECTOR_ASHR
) &&
1567 node
[0] == utils::mkConst(utils::getSize(node
), 0));
1571 Node RewriteRule
<ShiftZero
>::apply(TNode node
) {
1572 Debug("bv-rewrite") << "RewriteRule<ShiftZero>(" << node
<< ")" << std::endl
;
1576 /* -------------------------------------------------------------------------- */
1581 * (bvugt (bvurem T x) x)
1582 * ==> (ite (= x 0_k) (bvugt T x) false)
1583 * ==> (and (=> (= x 0_k) (bvugt T x)) (=> (not (= x 0_k)) false))
1584 * ==> (and (=> (= x 0_k) (bvugt T x)) (= x 0_k))
1585 * ==> (and (bvugt T x) (= x 0_k))
1586 * ==> (and (bvugt T 0_k) (= x 0_k))
1590 inline bool RewriteRule
<UgtUrem
>::applies(TNode node
)
1592 return (node
.getKind() == kind::BITVECTOR_UGT
1593 && node
[0].getKind() == kind::BITVECTOR_UREM_TOTAL
1594 && node
[0][1] == node
[1]);
1598 inline Node RewriteRule
<UgtUrem
>::apply(TNode node
)
1600 Debug("bv-rewrite") << "RewriteRule<UgtUrem>(" << node
<< ")" << std::endl
;
1601 const Node
& T
= node
[0][0];
1602 const Node
& x
= node
[1];
1603 Node zero
= utils::mkConst(utils::getSize(x
), 0);
1604 NodeManager
* nm
= NodeManager::currentNM();
1605 return nm
->mkNode(kind::AND
,
1606 nm
->mkNode(kind::EQUAL
, x
, zero
),
1607 nm
->mkNode(kind::BITVECTOR_UGT
, T
, zero
));
1610 /* -------------------------------------------------------------------------- */
1615 * -a1 - a2 - ... - an + ak + .. ==> - (a1 + a2 + ... + an) + ak
1620 bool RewriteRule
<BBPlusNeg
>::applies(TNode node
) {
1621 if (node
.getKind() != kind::BITVECTOR_PLUS
) {
1625 unsigned neg_count
= 0;
1626 for(unsigned i
= 0; i
< node
.getNumChildren(); ++i
) {
1627 if (node
[i
].getKind()== kind::BITVECTOR_NEG
) {
1631 return neg_count
> 1;
1635 inline Node RewriteRule
<BBPlusNeg
>::apply(TNode node
)
1637 Debug("bv-rewrite") << "RewriteRule<BBPlusNeg>(" << node
<< ")" << std::endl
;
1638 NodeManager
*nm
= NodeManager::currentNM();
1639 std::vector
<Node
> children
;
1640 unsigned neg_count
= 0;
1641 for (unsigned i
= 0; i
< node
.getNumChildren(); ++i
)
1643 if (node
[i
].getKind() == kind::BITVECTOR_NEG
)
1646 children
.push_back(nm
->mkNode(kind::BITVECTOR_NOT
, node
[i
][0]));
1650 children
.push_back(node
[i
]);
1653 Assert(neg_count
!= 0);
1654 children
.push_back(utils::mkConst(utils::getSize(node
), neg_count
));
1656 return utils::mkNaryNode(kind::BITVECTOR_PLUS
, children
);
1659 /* -------------------------------------------------------------------------- */
1662 bool RewriteRule
<MergeSignExtend
>::applies(TNode node
) {
1663 if (node
.getKind() != kind::BITVECTOR_SIGN_EXTEND
||
1664 (node
[0].getKind() != kind::BITVECTOR_SIGN_EXTEND
&&
1665 node
[0].getKind() != kind::BITVECTOR_ZERO_EXTEND
))
1671 Node RewriteRule
<MergeSignExtend
>::apply(TNode node
) {
1672 Debug("bv-rewrite") << "RewriteRule<MergeSignExtend>(" << node
<< ")" << std::endl
;
1674 node
.getOperator().getConst
<BitVectorSignExtend
>().d_signExtendAmount
;
1676 NodeManager
* nm
= NodeManager::currentNM();
1677 if (node
[0].getKind() == kind::BITVECTOR_ZERO_EXTEND
) {
1678 unsigned amount2
= node
[0]
1680 .getConst
<BitVectorZeroExtend
>()
1681 .d_zeroExtendAmount
;
1684 NodeBuilder
<> nb(kind::BITVECTOR_SIGN_EXTEND
);
1685 Node op
= nm
->mkConst
<BitVectorSignExtend
>(BitVectorSignExtend(amount1
));
1686 nb
<< op
<< node
[0][0];
1690 NodeBuilder
<> nb(kind::BITVECTOR_ZERO_EXTEND
);
1691 Node op
= nm
->mkConst
<BitVectorZeroExtend
>(
1692 BitVectorZeroExtend(amount1
+ amount2
));
1693 nb
<< op
<< node
[0][0];
1697 Assert(node
[0].getKind() == kind::BITVECTOR_SIGN_EXTEND
);
1699 node
[0].getOperator().getConst
<BitVectorSignExtend
>().d_signExtendAmount
;
1700 return utils::mkSignExtend(node
[0][0], amount1
+ amount2
);
1703 /* -------------------------------------------------------------------------- */
1708 * Rewrite zero_extend(x^n, m) = c^n+m to
1710 * false if c[n+m-1:n] != 0
1711 * x = c[n-1:0] otherwise.
1714 inline bool RewriteRule
<ZeroExtendEqConst
>::applies(TNode node
) {
1715 return node
.getKind() == kind::EQUAL
&&
1716 ((node
[0].getKind() == kind::BITVECTOR_ZERO_EXTEND
&&
1717 node
[1].isConst()) ||
1718 (node
[1].getKind() == kind::BITVECTOR_ZERO_EXTEND
&&
1719 node
[0].isConst()));
1723 inline Node RewriteRule
<ZeroExtendEqConst
>::apply(TNode node
) {
1725 if (node
[0].getKind() == kind::BITVECTOR_ZERO_EXTEND
) {
1733 c
.getConst
<BitVector
>().extract(utils::getSize(c
) - 1, utils::getSize(t
));
1734 BitVector c_lo
= c
.getConst
<BitVector
>().extract(utils::getSize(t
) - 1, 0);
1735 BitVector zero
= BitVector(c_hi
.getSize(), Integer(0));
1738 return NodeManager::currentNM()->mkNode(kind::EQUAL
, t
,
1739 utils::mkConst(c_lo
));
1741 return utils::mkFalse();
1744 /* -------------------------------------------------------------------------- */
1749 * Rewrite sign_extend(x^n, m) = c^n+m to
1751 * x = c[n-1:0] if (c[n-1:n-1] == 0 && c[n+m-1:n] == 0) ||
1752 * (c[n-1:n-1] == 1 && c[n+m-1:n] == ~0)
1756 inline bool RewriteRule
<SignExtendEqConst
>::applies(TNode node
) {
1757 return node
.getKind() == kind::EQUAL
&&
1758 ((node
[0].getKind() == kind::BITVECTOR_SIGN_EXTEND
&&
1759 node
[1].isConst()) ||
1760 (node
[1].getKind() == kind::BITVECTOR_SIGN_EXTEND
&&
1761 node
[0].isConst()));
1765 inline Node RewriteRule
<SignExtendEqConst
>::apply(TNode node
) {
1767 if (node
[0].getKind() == kind::BITVECTOR_SIGN_EXTEND
) {
1774 unsigned pos_msb_t
= utils::getSize(t
) - 1;
1776 c
.getConst
<BitVector
>().extract(utils::getSize(c
) - 1, pos_msb_t
);
1777 BitVector c_lo
= c
.getConst
<BitVector
>().extract(pos_msb_t
, 0);
1778 BitVector zero
= BitVector(c_hi
.getSize(), Integer(0));
1780 if (c_hi
== zero
|| c_hi
== ~zero
) {
1781 return NodeManager::currentNM()->mkNode(kind::EQUAL
, t
,
1782 utils::mkConst(c_lo
));
1784 return utils::mkFalse();
1787 /* -------------------------------------------------------------------------- */
1790 * ZeroExtendUltConst
1792 * Rewrite zero_extend(x^n,m) < c^n+m to
1794 * x < c[n-1:0] if c[n+m-1:n] == 0.
1796 * Rewrite c^n+m < Rewrite zero_extend(x^n,m) to
1798 * c[n-1:0] < x if c[n+m-1:n] == 0.
1801 inline bool RewriteRule
<ZeroExtendUltConst
>::applies(TNode node
) {
1802 if (node
.getKind() == kind::BITVECTOR_ULT
&&
1803 ((node
[0].getKind() == kind::BITVECTOR_ZERO_EXTEND
&&
1804 node
[1].isConst()) ||
1805 (node
[1].getKind() == kind::BITVECTOR_ZERO_EXTEND
&&
1806 node
[0].isConst()))) {
1808 bool is_lhs
= node
[0].getKind() == kind::BITVECTOR_ZERO_EXTEND
;
1817 if (utils::getSize(t
) == utils::getSize(c
))
1822 BitVector bv_c
= c
.getConst
<BitVector
>();
1823 BitVector c_hi
= c
.getConst
<BitVector
>().extract(utils::getSize(c
) - 1,
1825 BitVector zero
= BitVector(c_hi
.getSize(), Integer(0));
1827 return c_hi
== zero
;
1833 inline Node RewriteRule
<ZeroExtendUltConst
>::apply(TNode node
) {
1835 bool is_lhs
= node
[0].getKind() == kind::BITVECTOR_ZERO_EXTEND
;
1844 utils::mkConst(c
.getConst
<BitVector
>().extract(utils::getSize(t
) - 1, 0));
1847 return NodeManager::currentNM()->mkNode(kind::BITVECTOR_ULT
, t
, c_lo
);
1849 return NodeManager::currentNM()->mkNode(kind::BITVECTOR_ULT
, c_lo
, t
);
1852 /* -------------------------------------------------------------------------- */
1855 * SignExtendUltConst
1857 * Rewrite sign_extend(x^n,m) < c^n+m to
1859 * x < c[n-1:0] if (c <= (1 << (n - 1))) || (c >= (~0 << (n - 1)))
1860 * x[n-1:n-1] = 0 if (1 << (n - 1)) < c <= (~0 << (n - 1)).
1862 * Rewrite c^n+m < sign_extend(x^n,m) to
1864 * c[n-1:0] < x if (c < (1 << (n - 1))) || (c >= ~(1 << (n-1)))
1865 * x[n-1:n-1] = 1 if ~(~0 << (n-1)) <= c <= ~(1 << (n-1))
1867 * where ~(~0 << (n - 1)) == (1 << (n - 1)) - 1
1871 inline bool RewriteRule
<SignExtendUltConst
>::applies(TNode node
)
1873 if (node
.getKind() == kind::BITVECTOR_ULT
1874 && ((node
[0].getKind() == kind::BITVECTOR_SIGN_EXTEND
1875 && node
[1].isConst())
1876 || (node
[1].getKind() == kind::BITVECTOR_SIGN_EXTEND
1877 && node
[0].isConst())))
1880 bool is_lhs
= node
[0].getKind() == kind::BITVECTOR_SIGN_EXTEND
;
1891 BitVector bv_c
= c
.getConst
<BitVector
>();
1892 unsigned size_c
= utils::getSize(c
);
1893 unsigned msb_x_pos
= utils::getSize(x
) - 1;
1895 BitVector bv_msb_x
= BitVector(size_c
).setBit(msb_x_pos
, true);
1897 BitVector bv_upper_bits
=
1898 (~BitVector(size_c
)).leftShift(BitVector(size_c
, msb_x_pos
));
1901 && (bv_c
<= bv_msb_x
|| bv_c
>= bv_upper_bits
1902 || (bv_msb_x
< bv_c
&& bv_c
<= bv_upper_bits
)))
1904 && (bv_c
< bv_msb_x
|| bv_c
>= ~bv_msb_x
1905 || (~bv_upper_bits
<= bv_c
&& bv_c
<= ~bv_msb_x
)));
1911 inline Node RewriteRule
<SignExtendUltConst
>::apply(TNode node
)
1914 bool is_lhs
= node
[0].getKind() == kind::BITVECTOR_SIGN_EXTEND
;
1925 BitVector bv_c
= c
.getConst
<BitVector
>();
1927 unsigned size_c
= utils::getSize(c
);
1928 unsigned msb_x_pos
= utils::getSize(x
) - 1;
1929 Node c_lo
= utils::mkConst(bv_c
.extract(msb_x_pos
, 0));
1931 BitVector bv_msb_x
= BitVector(size_c
).setBit(msb_x_pos
, true);
1933 BitVector bv_upper_bits
=
1934 (~BitVector(size_c
)).leftShift(BitVector(size_c
, msb_x_pos
));
1936 NodeManager
* nm
= NodeManager::currentNM();
1940 if (bv_msb_x
< bv_c
&& bv_c
<= bv_upper_bits
)
1942 Node msb_x
= utils::mkExtract(x
, msb_x_pos
, msb_x_pos
);
1943 return nm
->mkNode(kind::EQUAL
, msb_x
, utils::mkZero(1));
1946 Assert(bv_c
<= bv_msb_x
|| bv_c
>= bv_upper_bits
);
1947 return nm
->mkNode(kind::BITVECTOR_ULT
, x
, c_lo
);
1951 if (~bv_upper_bits
<= bv_c
&& bv_c
<= ~bv_msb_x
)
1953 Node msb_x
= utils::mkExtract(x
, msb_x_pos
, msb_x_pos
);
1954 return nm
->mkNode(kind::EQUAL
, msb_x
, utils::mkOne(1));
1957 Assert(bv_c
< bv_msb_x
|| bv_c
>= ~bv_msb_x
);
1958 return nm
->mkNode(kind::BITVECTOR_ULT
, c_lo
, x
);
1961 /* -------------------------------------------------------------------------- */
1964 bool RewriteRule
<MultSlice
>::applies(TNode node
) {
1965 if (node
.getKind() != kind::BITVECTOR_MULT
|| node
.getNumChildren() != 2) {
1968 return utils::getSize(node
[0]) % 2 == 0;
1972 * Expressses the multiplication in terms of the top and bottom
1973 * slices of the terms. Note increases circuit size, but could
1974 * lead to simplifications (use wisely!).
1981 inline Node RewriteRule
<MultSlice
>::apply(TNode node
)
1983 Debug("bv-rewrite") << "RewriteRule<MultSlice>(" << node
<< ")" << std::endl
;
1984 NodeManager
*nm
= NodeManager::currentNM();
1985 unsigned bitwidth
= utils::getSize(node
[0]);
1986 Node zeros
= utils::mkConst(bitwidth
/ 2, 0);
1988 Node bottom_a
= utils::mkExtract(a
, bitwidth
/ 2 - 1, 0);
1989 Node top_a
= utils::mkExtract(a
, bitwidth
- 1, bitwidth
/ 2);
1991 Node bottom_b
= utils::mkExtract(b
, bitwidth
/ 2 - 1, 0);
1992 Node top_b
= utils::mkExtract(b
, bitwidth
- 1, bitwidth
/ 2);
1994 Node term1
= nm
->mkNode(kind::BITVECTOR_MULT
,
1995 nm
->mkNode(kind::BITVECTOR_CONCAT
, zeros
, bottom_a
),
1996 nm
->mkNode(kind::BITVECTOR_CONCAT
, zeros
, bottom_b
));
1998 Node term2
= nm
->mkNode(kind::BITVECTOR_CONCAT
,
1999 nm
->mkNode(kind::BITVECTOR_MULT
, top_b
, bottom_a
),
2001 Node term3
= nm
->mkNode(kind::BITVECTOR_CONCAT
,
2002 nm
->mkNode(kind::BITVECTOR_MULT
, top_a
, bottom_b
),
2004 return nm
->mkNode(kind::BITVECTOR_PLUS
, term1
, term2
, term3
);
2007 /* -------------------------------------------------------------------------- */
2010 * x < y + 1 <=> (not y < x) and y != 1...1
2017 bool RewriteRule
<UltPlusOne
>::applies(TNode node
) {
2018 if (node
.getKind() != kind::BITVECTOR_ULT
) return false;
2021 if (y1
.getKind() != kind::BITVECTOR_PLUS
) return false;
2022 if (y1
[0].getKind() != kind::CONST_BITVECTOR
&&
2023 y1
[1].getKind() != kind::CONST_BITVECTOR
)
2026 if (y1
[0].getKind() == kind::CONST_BITVECTOR
&&
2027 y1
[1].getKind() == kind::CONST_BITVECTOR
)
2030 if (y1
.getNumChildren() != 2)
2033 TNode one
= y1
[0].getKind() == kind::CONST_BITVECTOR
? y1
[0] : y1
[1];
2034 if (one
!= utils::mkConst(utils::getSize(one
), 1)) return false;
2039 inline Node RewriteRule
<UltPlusOne
>::apply(TNode node
)
2041 Debug("bv-rewrite") << "RewriteRule<UltPlusOne>(" << node
<< ")" << std::endl
;
2042 NodeManager
*nm
= NodeManager::currentNM();
2045 TNode y
= y1
[0].getKind() != kind::CONST_BITVECTOR
? y1
[0] : y1
[1];
2046 unsigned size
= utils::getSize(x
);
2048 nm
->mkNode(kind::NOT
, nm
->mkNode(kind::EQUAL
, y
, utils::mkOnes(size
)));
2050 nm
->mkNode(kind::NOT
, nm
->mkNode(kind::BITVECTOR_ULT
, y
, x
));
2051 return nm
->mkNode(kind::AND
, not_y_eq_1
, not_y_lt_x
);
2054 /* -------------------------------------------------------------------------- */
2057 * x ^(x-1) = 0 => 1 << sk
2058 * WARNING: this is an **EQUISATISFIABLE** transformation!
2059 * Only to be called on top level assertions.
2066 bool RewriteRule
<IsPowerOfTwo
>::applies(TNode node
) {
2067 if (node
.getKind()!= kind::EQUAL
) return false;
2068 if (node
[0].getKind() != kind::BITVECTOR_AND
&&
2069 node
[1].getKind() != kind::BITVECTOR_AND
)
2071 if (!utils::isZero(node
[0]) &&
2072 !utils::isZero(node
[1]))
2075 TNode t
= !utils::isZero(node
[0])? node
[0]: node
[1];
2076 if (t
.getNumChildren() != 2) return false;
2079 unsigned size
= utils::getSize(t
);
2080 if(size
< 2) return false;
2081 Node diff
= Rewriter::rewrite(
2082 NodeManager::currentNM()->mkNode(kind::BITVECTOR_SUB
, a
, b
));
2083 return (diff
.isConst() && (diff
== utils::mkConst(size
, 1u) || diff
== utils::mkOnes(size
)));
2087 inline Node RewriteRule
<IsPowerOfTwo
>::apply(TNode node
)
2089 Debug("bv-rewrite") << "RewriteRule<IsPowerOfTwo>(" << node
<< ")"
2091 NodeManager
*nm
= NodeManager::currentNM();
2092 TNode term
= utils::isZero(node
[0]) ? node
[1] : node
[0];
2095 unsigned size
= utils::getSize(term
);
2096 Node diff
= Rewriter::rewrite(nm
->mkNode(kind::BITVECTOR_SUB
, a
, b
));
2097 Assert(diff
.isConst());
2098 TNode x
= diff
== utils::mkConst(size
, 1u) ? a
: b
;
2099 Node one
= utils::mkConst(size
, 1u);
2100 Node sk
= utils::mkVar(size
);
2101 Node sh
= nm
->mkNode(kind::BITVECTOR_SHL
, one
, sk
);
2102 Node x_eq_sh
= nm
->mkNode(kind::EQUAL
, x
, sh
);
2106 /* -------------------------------------------------------------------------- */
2110 * sign_extend(x+t,n) * sign_extend(a,m) < sign_extend(x,n) * sign_extend(a,m)
2115 * (= (bvslt (bvadd x t) x) (bvsgt a zero))
2119 * zero_extend(x+t,n) * sign_extend(a,m) < zero_extend(x,n) * sign_extend(a,m)
2124 * (= (bvult (bvadd x t) x) (bvsgt a zero))
2126 * where n and m are sufficiently big to not produce an overflow for
2127 * the multiplications.
2129 * These patterns occur in the quantified BV benchmark family 'ranking',
2130 * where the BV engine struggles due to the high bit widths of the
2131 * multiplication's operands.
2133 static std::tuple
<Node
, Node
, bool>
2134 extract_ext_tuple(TNode node
)
2138 for (unsigned i
= 0; i
< 2; ++i
)
2140 if (a
.getKind() == kind::BITVECTOR_CONCAT
2141 && b
.getKind() == kind::BITVECTOR_SIGN_EXTEND
2142 && a
[0] == utils::mkZero(utils::getSize(a
[0]))
2143 && utils::getSize(a
[1]) <= utils::getSize(a
[0])
2144 && utils::getSize(b
[0]) <= utils::getSignExtendAmount(b
))
2146 return std::make_tuple(a
[1], b
[0], false);
2149 && a
.getKind() == kind::BITVECTOR_SIGN_EXTEND
2150 && b
.getKind() == kind::BITVECTOR_SIGN_EXTEND
2151 && utils::getSize(a
[0]) <= utils::getSignExtendAmount(a
)
2152 && utils::getSize(b
[0]) <= utils::getSignExtendAmount(b
))
2154 return std::make_tuple(a
[0], b
[0], true);
2158 return std::make_tuple(Node::null(), Node::null(), false);
2161 /* -------------------------------------------------------------------------- */
2164 bool RewriteRule
<MultSltMult
>::applies(TNode node
)
2166 if (node
.getKind() != kind::BITVECTOR_SLT
2167 || node
[0].getKind() != kind::BITVECTOR_MULT
2168 || node
[1].getKind() != kind::BITVECTOR_MULT
)
2171 if (node
[0].getNumChildren() > 2 || node
[1].getNumChildren() > 2)
2174 bool is_sext_l
, is_sext_r
;
2177 std::tie(ml
[0], ml
[1], is_sext_l
) = extract_ext_tuple(node
[0]);
2181 std::tie(mr
[0], mr
[1], is_sext_r
) = extract_ext_tuple(node
[1]);
2185 if (is_sext_l
!= is_sext_r
)
2189 if (ml
[0].getKind() == kind::BITVECTOR_PLUS
)
2194 else if (ml
[1].getKind() == kind::BITVECTOR_PLUS
)
2202 if (addxt
.getNumChildren() > 2)
2209 else if (mr
[1] == a
)
2216 return (addxt
[0] == x
|| addxt
[1] == x
);
2220 Node RewriteRule
<MultSltMult
>::apply(TNode node
)
2225 std::tie(ml
[0], ml
[1], is_sext
) = extract_ext_tuple(node
[0]);
2226 std::tie(mr
[0], mr
[1], std::ignore
) = extract_ext_tuple(node
[1]);
2228 TNode addxt
, x
, t
, a
;
2229 if (ml
[0].getKind() == kind::BITVECTOR_PLUS
)
2236 Assert(ml
[1].getKind() == kind::BITVECTOR_PLUS
);
2241 x
= (mr
[0] == a
) ? mr
[1] : mr
[0];
2242 t
= (addxt
[0] == x
) ? addxt
[1] : addxt
[0];
2244 NodeManager
*nm
= NodeManager::currentNM();
2245 Node zero_t
= utils::mkZero(utils::getSize(t
));
2246 Node zero_a
= utils::mkZero(utils::getSize(a
));
2248 NodeBuilder
<> nb(kind::AND
);
2249 Kind k
= is_sext
? kind::BITVECTOR_SLT
: kind::BITVECTOR_ULT
;
2250 nb
<< t
.eqNode(zero_t
).notNode();
2251 nb
<< a
.eqNode(zero_a
).notNode();
2252 nb
<< nm
->mkNode(k
, addxt
, x
)
2253 .eqNode(nm
->mkNode(kind::BITVECTOR_SGT
, a
, zero_a
));
2254 return nb
.constructNode();
2258 } // namespace theory