From 2d3c3cd7234488982ad8b769d787a6c69bb9f19e Mon Sep 17 00:00:00 2001 From: Andres Noetzli Date: Tue, 1 Feb 2022 13:58:41 -0800 Subject: [PATCH] [BV] Fix strategy for `RewriteExtract` (#8011) `RewriteExtract` was being too eager to return `REWRITE_DONE`. In particular, it could happen that a term could be rewritten by a series of `ExtractExtract` and `ExtractConcat` rewrites, but the method would return `REWRITE_AGAIN` after the first application of `ExtractExtract`. This commit fixes the method to be more conservative and return `REWRITE_AGAIN` whenever a rewrite changed the node being rewritten. Additionally, the commit makes constant folding the last step (to maximize the chances that it applies) and makes `ExtractExtract` rewrite multiple nested applications of `extract` with a single application. --- src/theory/bv/theory_bv_rewrite_rules_core.h | 15 ++++++++----- src/theory/bv/theory_bv_rewriter.cpp | 22 ++++++++++++-------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/theory/bv/theory_bv_rewrite_rules_core.h b/src/theory/bv/theory_bv_rewrite_rules_core.h index cdb0a6f81..d3caec63a 100644 --- a/src/theory/bv/theory_bv_rewrite_rules_core.h +++ b/src/theory/bv/theory_bv_rewrite_rules_core.h @@ -248,12 +248,17 @@ Node RewriteRule::apply(TNode node) { Debug("bv-rewrite") << "RewriteRule(" << node << ")" << std::endl; // x[i:j][k:l] ~> x[k+j:l+j] + uint32_t j = 0; Node child = node[0]; - unsigned k = utils::getExtractHigh(node); - unsigned l = utils::getExtractLow(node); - unsigned j = utils::getExtractLow(child); - - Node result = utils::mkExtract(child[0], k + j, l + j); + do + { + j += utils::getExtractLow(child); + child = child[0]; + } while (child.getKind() == kind::BITVECTOR_EXTRACT); + + uint32_t k = utils::getExtractHigh(node); + uint32_t l = utils::getExtractLow(node); + Node result = utils::mkExtract(child, k + j, l + j); return result; } diff --git a/src/theory/bv/theory_bv_rewriter.cpp b/src/theory/bv/theory_bv_rewriter.cpp index 4bfddf1a7..bfadbd370 100644 --- a/src/theory/bv/theory_bv_rewriter.cpp +++ b/src/theory/bv/theory_bv_rewriter.cpp @@ -263,17 +263,21 @@ RewriteResponse TheoryBVRewriter::RewriteExtract(TNode node, bool prerewrite) { } } - - resultNode = LinearRewriteStrategy - < RewriteRule, + resultNode = LinearRewriteStrategy< + // We could have an extract over extract RewriteRule, - // We could get another extract over extract + // The extract may cover the whole bit-vector RewriteRule, - // At this point only Extract-Whole could apply - RewriteRule - >::apply(node); - - return RewriteResponse(REWRITE_DONE, resultNode); + // Rewrite extracts over wide multiplications + RewriteRule, + // Perform constant folding last to maximize chances that it applies + RewriteRule>::apply(node); + + // There are terms that can be rewritten by repeatedly alternating between + // ExtractExtract and ExtractConcat, so we have to be conservative here and + // return REWRITE_AGAIN if the node changed. + return RewriteResponse(resultNode != node ? REWRITE_AGAIN : REWRITE_DONE, + resultNode); } RewriteResponse TheoryBVRewriter::RewriteConcat(TNode node, bool prerewrite) -- 2.30.2