namespace theory {
namespace bv {
+/* -------------------------------------------------------------------------- */
+
template<> inline
bool RewriteRule<ConcatFlatten>::applies(TNode node) {
return (node.getKind() == kind::BITVECTOR_CONCAT);
return resultNode;
}
+/* -------------------------------------------------------------------------- */
+
template<> inline
bool RewriteRule<ConcatExtractMerge>::applies(TNode node) {
return (node.getKind() == kind::BITVECTOR_CONCAT);
return utils::mkConcat(mergedExtracts);
}
+/* -------------------------------------------------------------------------- */
+
template<> inline
bool RewriteRule<ConcatConstantMerge>::applies(TNode node) {
return node.getKind() == kind::BITVECTOR_CONCAT;
return utils::mkConcat(mergedConstants);
}
+/* -------------------------------------------------------------------------- */
+
template<> inline
bool RewriteRule<ExtractWhole>::applies(TNode node) {
if (node.getKind() != kind::BITVECTOR_EXTRACT) return false;
return node[0];
}
+/* -------------------------------------------------------------------------- */
+
template<> inline
bool RewriteRule<ExtractConstant>::applies(TNode node) {
if (node.getKind() != kind::BITVECTOR_EXTRACT) return false;
return utils::mkConst(childValue.extract(utils::getExtractHigh(node), utils::getExtractLow(node)));
}
+/* -------------------------------------------------------------------------- */
+
template<> inline
bool RewriteRule<ExtractConcat>::applies(TNode node) {
//Debug("bv-rewrite") << "RewriteRule<ExtractConcat>(" << node << ")" << std::endl;
return utils::mkConcat(resultChildren);
}
+/* -------------------------------------------------------------------------- */
+
template<> inline
bool RewriteRule<ExtractExtract>::applies(TNode node) {
if (node.getKind() != kind::BITVECTOR_EXTRACT) return false;
return result;
}
+/* -------------------------------------------------------------------------- */
+
template<> inline
bool RewriteRule<FailEq>::applies(TNode node) {
//Debug("bv-rewrite") << "RewriteRule<FailEq>(" << node << ")" << std::endl;
return utils::mkFalse();
}
+/* -------------------------------------------------------------------------- */
+
template<> inline
bool RewriteRule<SimplifyEq>::applies(TNode node) {
if (node.getKind() != kind::EQUAL) return false;
return utils::mkTrue();
}
+/* -------------------------------------------------------------------------- */
+
template<> inline
bool RewriteRule<ReflexivityEq>::applies(TNode node) {
return (node.getKind() == kind::EQUAL && node[0] < node[1]);
namespace theory {
namespace bv {
-// FIXME: this rules subsume the constant evaluation ones
+
+/* -------------------------------------------------------------------------- */
/**
* BvIteConstCond
return utils::isZero(node[0]) ? node[2] : node[1];
}
+/* -------------------------------------------------------------------------- */
+
/**
* BvIteEqualChildren
*
return node[1];
}
+/* -------------------------------------------------------------------------- */
+
/**
* BvIteConstChildren
*
return NodeManager::currentNM()->mkNode(kind::BITVECTOR_NOT, node[0]);
}
+/* -------------------------------------------------------------------------- */
+
/**
* BvIteEqualCond
*
return NodeManager::currentNM()->mkNode(kind::BITVECTOR_ITE, node[0], t0, e1);
}
+/* -------------------------------------------------------------------------- */
+
/**
* BvIteMergeThenIf
*
return nm->mkNode(kind::BITVECTOR_ITE, cond, node[1][2], node[2]);
}
+/* -------------------------------------------------------------------------- */
+
/**
* BvIteMergeElseIf
*
return nm->mkNode(kind::BITVECTOR_ITE, cond, node[1][1], node[2]);
}
+/* -------------------------------------------------------------------------- */
+
/**
* BvIteMergeThenElse
*
return nm->mkNode(kind::BITVECTOR_ITE, cond, node[2][2], node[1]);
}
+/* -------------------------------------------------------------------------- */
+
/**
* BvIteMergeElseElse
*
return nm->mkNode(kind::BITVECTOR_ITE, cond, node[2][1], node[1]);
}
+/* -------------------------------------------------------------------------- */
+
/**
* BvComp
*
: Node(node[0]);
}
+/* -------------------------------------------------------------------------- */
+
/**
* ShlByConst
*
return utils::mkConcat(left, right);
}
+/* -------------------------------------------------------------------------- */
+
/**
* LshrByConst
*
return utils::mkConcat(left, right);
}
+/* -------------------------------------------------------------------------- */
+
/**
* AshrByConst
*
return utils::mkConcat(left, right);
}
+/* -------------------------------------------------------------------------- */
+
/**
* BitwiseIdemp
*
return node[0];
}
+/* -------------------------------------------------------------------------- */
+
/**
* AndZero
*
return utils::mkConst(utils::getSize(node), 0);
}
+/* -------------------------------------------------------------------------- */
+
/**
* AndOne
*
}
}
+/* -------------------------------------------------------------------------- */
+
+/**
+ * AndConcatPullUp
+ *
+ * x_m & concat(0_n, z_[m-n]) --> concat(0_n, x[m-n-1:0] & z)
+ */
+
+template <>
+inline bool RewriteRule<AndConcatPullUp>::applies(TNode node)
+{
+ if (node.getKind() != kind::BITVECTOR_AND) return false;
+
+ TNode n;
+
+ for (const TNode& c : node)
+ {
+ if (c.getKind() == kind::BITVECTOR_CONCAT)
+ {
+ n = c[0];
+ break;
+ }
+ }
+ if (n.isNull()) return false;
+ return utils::isZero(n);
+}
+
+template <>
+inline Node RewriteRule<AndConcatPullUp>::apply(TNode node)
+{
+ Debug("bv-rewrite") << "RewriteRule<AndConcatPullUp>(" << node << ")"
+ << std::endl;
+ uint32_t m, n;
+ TNode concat;
+ Node x, z;
+ NodeBuilder<> xb(kind::BITVECTOR_AND);
+ NodeBuilder<> zb(kind::BITVECTOR_CONCAT);
+
+ for (const TNode& c : node)
+ {
+ if (concat.isNull() && c.getKind() == kind::BITVECTOR_CONCAT)
+ {
+ concat = c;
+ }
+ else
+ {
+ xb << c;
+ }
+ }
+ x = xb.getNumChildren() > 1 ? xb.constructNode() : xb[0];
+ Assert(utils::isZero(concat[0]));
+
+ m = utils::getSize(x);
+ n = utils::getSize(concat[0]);
+
+ for (size_t i = 1, nchildren = concat.getNumChildren(); i < nchildren; i++)
+ {
+ zb << concat[i];
+ }
+ z = zb.getNumChildren() > 1 ? zb.constructNode() : zb[0];
+ Assert(utils::getSize(z) == m - n);
+
+ return utils::mkConcat(
+ concat[0],
+ NodeManager::currentNM()->mkNode(
+ kind::BITVECTOR_AND, utils::mkExtract(x, m - n - 1, 0), z));
+}
+
+/* -------------------------------------------------------------------------- */
+
/**
* OrZero
- *
+ *
* (a bvor 0) ==> a
*/
}
}
+/* -------------------------------------------------------------------------- */
+
/**
* OrOne
*
return utils::mkOnes(utils::getSize(node));
}
+/* -------------------------------------------------------------------------- */
/**
* XorDuplicate
return utils::mkZero(utils::getSize(node));
}
+/* -------------------------------------------------------------------------- */
+
/**
* XorOne
*
return result;
}
+/* -------------------------------------------------------------------------- */
+
/**
* XorZero
*
return res;
}
+/* -------------------------------------------------------------------------- */
+
/**
* BitwiseNotAnd
*
return utils::mkZero(utils::getSize(node));
}
+/* -------------------------------------------------------------------------- */
+
/**
* BitwiseNegOr
*
return utils::mkOnes(size);
}
+/* -------------------------------------------------------------------------- */
+
/**
* XorNot
*
return NodeManager::currentNM()->mkNode(kind::BITVECTOR_XOR, a, b);
}
+/* -------------------------------------------------------------------------- */
+
/**
* NotXor
*
return utils::mkSortedNode(kind::BITVECTOR_XOR, children);
}
+/* -------------------------------------------------------------------------- */
+
/**
* NotIdemp
*
return node[0][0];
}
-
+/* -------------------------------------------------------------------------- */
/**
* LtSelf
return utils::mkFalse();
}
+/* -------------------------------------------------------------------------- */
+
/**
* LteSelf
*
return utils::mkTrue();
}
+/* -------------------------------------------------------------------------- */
+
/**
* ZeroUlt
*
return nm->mkNode(kind::NOT, nm->mkNode(kind::EQUAL, node[0], node[1]));
}
+/* -------------------------------------------------------------------------- */
+
/**
* UltZero
*
}
+/* -------------------------------------------------------------------------- */
+
/**
*
*/
kind::EQUAL, node[0], utils::mkZero(utils::getSize(node[0])));
}
+/* -------------------------------------------------------------------------- */
+
/**
*
*/
kind::EQUAL, most_significant_bit, utils::mkOne(1));
}
+/* -------------------------------------------------------------------------- */
+
/**
* UltSelf
*
}
+/* -------------------------------------------------------------------------- */
+
/**
* UleZero
*
return NodeManager::currentNM()->mkNode(kind::EQUAL, node[0], node[1]);
}
+/* -------------------------------------------------------------------------- */
+
/**
* UleSelf
*
return utils::mkTrue();
}
+/* -------------------------------------------------------------------------- */
/**
* ZeroUle
return utils::mkTrue();
}
+/* -------------------------------------------------------------------------- */
+
/**
* UleMax
*
return utils::mkTrue();
}
+/* -------------------------------------------------------------------------- */
+
/**
* NotUlt
*
return NodeManager::currentNM()->mkNode(kind::BITVECTOR_ULE, b, a);
}
+/* -------------------------------------------------------------------------- */
+
/**
* NotUle
*
return NodeManager::currentNM()->mkNode(kind::BITVECTOR_ULT, b, a);
}
+/* -------------------------------------------------------------------------- */
+
/**
* MultPow2
*
return utils::mkConcat(extract, zeros);
}
+/* -------------------------------------------------------------------------- */
+
/**
* ExtractMultLeadingBit
*
return result;
}
+/* -------------------------------------------------------------------------- */
+
/**
* NegIdemp
*
return node[0][0];
}
+/* -------------------------------------------------------------------------- */
+
/**
* UdivPow2
*
return ret;
}
+/* -------------------------------------------------------------------------- */
+
/**
* UdivZero
*
return utils::mkOnes(utils::getSize(node));
}
+/* -------------------------------------------------------------------------- */
+
/**
* UdivOne
*
return node[0];
}
+/* -------------------------------------------------------------------------- */
+
/**
* UremPow2
*
return ret;
}
+/* -------------------------------------------------------------------------- */
+
/**
* UremOne
*
return utils::mkConst(utils::getSize(node), 0);
}
+/* -------------------------------------------------------------------------- */
+
/**
* UremSelf
*
return utils::mkConst(utils::getSize(node), 0);
}
+/* -------------------------------------------------------------------------- */
+
/**
* ShiftZero
*
return node[0];
}
+/* -------------------------------------------------------------------------- */
+
/**
* BBPlusNeg
*
return utils::mkNaryNode(kind::BITVECTOR_PLUS, children);
}
+/* -------------------------------------------------------------------------- */
+
template<> inline
bool RewriteRule<MergeSignExtend>::applies(TNode node) {
if (node.getKind() != kind::BITVECTOR_SIGN_EXTEND ||
return utils::mkSignExtend(node[0][0], amount1 + amount2);
}
+/* -------------------------------------------------------------------------- */
+
/**
* ZeroExtendEqConst
*
return utils::mkFalse();
}
+/* -------------------------------------------------------------------------- */
+
/**
* SignExtendEqConst
*
return utils::mkFalse();
}
+/* -------------------------------------------------------------------------- */
+
/**
* ZeroExtendUltConst
*
return NodeManager::currentNM()->mkNode(kind::BITVECTOR_ULT, c_lo, t);
}
+/* -------------------------------------------------------------------------- */
+
/**
* SignExtendUltConst
*
return nm->mkNode(kind::BITVECTOR_ULT, c_lo, x);
}
+/* -------------------------------------------------------------------------- */
+
template<> inline
bool RewriteRule<MultSlice>::applies(TNode node) {
if (node.getKind() != kind::BITVECTOR_MULT || node.getNumChildren() != 2) {
return nm->mkNode(kind::BITVECTOR_PLUS, term1, term2, term3);
}
+/* -------------------------------------------------------------------------- */
+
/**
* x < y + 1 <=> (not y < x) and y != 1...1
*
return nm->mkNode(kind::AND, not_y_eq_1, not_y_lt_x);
}
+/* -------------------------------------------------------------------------- */
+
/**
* x ^(x-1) = 0 => 1 << sk
* WARNING: this is an **EQUISATISFIABLE** transformation!
return x_eq_sh;
}
+/* -------------------------------------------------------------------------- */
+
/**
* Rewrite
* sign_extend(x+t,n) * sign_extend(a,m) < sign_extend(x,n) * sign_extend(a,m)
return std::make_tuple(Node::null(), Node::null(), false);
}
+/* -------------------------------------------------------------------------- */
+
template<> inline
bool RewriteRule<MultSltMult>::applies(TNode node)
{
return RewriteResponse(REWRITE_DONE, resultNode);
}
-
-RewriteResponse TheoryBVRewriter::RewriteConcat(TNode node, bool prerewrite) {
-
- Node resultNode = LinearRewriteStrategy
- < RewriteRule<ConcatFlatten>,
+RewriteResponse TheoryBVRewriter::RewriteConcat(TNode node, bool prerewrite)
+{
+ Node resultNode = LinearRewriteStrategy<
+ RewriteRule<ConcatFlatten>,
// Flatten the top level concatenations
RewriteRule<ConcatExtractMerge>,
// Merge the adjacent extracts on non-constants
RewriteRule<ConcatConstantMerge>,
// Merge the adjacent extracts on constants
- ApplyRuleToChildren<kind::BITVECTOR_CONCAT, ExtractWhole>
- >::apply(node);
- return RewriteResponse(REWRITE_DONE, resultNode);
+ ApplyRuleToChildren<kind::BITVECTOR_CONCAT, ExtractWhole>>::apply(node);
+ return RewriteResponse(REWRITE_DONE, resultNode);
}
-RewriteResponse TheoryBVRewriter::RewriteAnd(TNode node, bool prerewrite) {
+RewriteResponse TheoryBVRewriter::RewriteAnd(TNode node, bool prerewrite)
+{
Node resultNode = node;
- resultNode = LinearRewriteStrategy
- < RewriteRule<FlattenAssocCommutNoDuplicates>,
- RewriteRule<AndSimplify>
- >::apply(node);
-
- if (!prerewrite) {
- resultNode = LinearRewriteStrategy
- < RewriteRule<BitwiseSlicing>
- >::apply(resultNode);
-
- if (resultNode.getKind() != node.getKind()) {
- return RewriteResponse(REWRITE_AGAIN_FULL, resultNode);
+ resultNode =
+ LinearRewriteStrategy<RewriteRule<FlattenAssocCommutNoDuplicates>,
+ RewriteRule<AndSimplify>,
+ RewriteRule<AndConcatPullUp>>::apply(node);
+
+ if (!prerewrite)
+ {
+ resultNode =
+ LinearRewriteStrategy<RewriteRule<BitwiseSlicing>>::apply(resultNode);
+
+ if (resultNode.getKind() != node.getKind())
+ {
+ return RewriteResponse(REWRITE_AGAIN_FULL, resultNode);
}
}
-
- return RewriteResponse(REWRITE_DONE, resultNode);
+
+ return RewriteResponse(REWRITE_DONE, resultNode);
}
RewriteResponse TheoryBVRewriter::RewriteOr(TNode node, bool prerewrite){