LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/theory/bv - theory_bv_rewrite_rules_core.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 176 176 100.0 %
Date: 2026-04-14 10:42:21 Functions: 20 20 100.0 %
Branches: 77 94 81.9 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * This file is part of the cvc5 project.
       3                 :            :  *
       4                 :            :  * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS
       5                 :            :  * in the top-level source directory and their institutional affiliations.
       6                 :            :  * All rights reserved.  See the file COPYING in the top-level source
       7                 :            :  * directory for licensing information.
       8                 :            :  * ****************************************************************************
       9                 :            :  *
      10                 :            :  * Core rewrite rules of the BV theory.
      11                 :            :  */
      12                 :            : 
      13                 :            : #include "cvc5_private.h"
      14                 :            : 
      15                 :            : #ifndef CVC5__THEORY__BV__THEORY_BV_REWRITE_RULES_CORE_H
      16                 :            : #define CVC5__THEORY__BV__THEORY_BV_REWRITE_RULES_CORE_H
      17                 :            : 
      18                 :            : #include "theory/bv/theory_bv_rewrite_rules.h"
      19                 :            : #include "theory/bv/theory_bv_utils.h"
      20                 :            : #include "util/bitvector.h"
      21                 :            : 
      22                 :            : namespace cvc5::internal {
      23                 :            : namespace theory {
      24                 :            : namespace bv {
      25                 :            : 
      26                 :            : /* -------------------------------------------------------------------------- */
      27                 :            : 
      28                 :            : template <>
      29                 :     872110 : inline bool RewriteRule<ConcatFlatten>::applies(TNode node)
      30                 :            : {
      31                 :     872110 :   return (node.getKind() == Kind::BITVECTOR_CONCAT);
      32                 :            : }
      33                 :            : 
      34                 :            : template <>
      35                 :     436055 : inline Node RewriteRule<ConcatFlatten>::apply(TNode node)
      36                 :            : {
      37         [ +  - ]:     872110 :   Trace("bv-rewrite") << "RewriteRule<ConcatFlatten>(" << node << ")"
      38                 :     436055 :                       << std::endl;
      39                 :     436055 :   NodeBuilder result(node.getNodeManager(), Kind::BITVECTOR_CONCAT);
      40                 :     436055 :   std::vector<Node> processing_stack;
      41                 :     436055 :   processing_stack.push_back(node);
      42         [ +  + ]:    3249893 :   while (!processing_stack.empty())
      43                 :            :   {
      44                 :    2813838 :     Node current = processing_stack.back();
      45                 :    2813838 :     processing_stack.pop_back();
      46         [ +  + ]:    2813838 :     if (current.getKind() == Kind::BITVECTOR_CONCAT)
      47                 :            :     {
      48         [ +  + ]:    2828405 :       for (int i = current.getNumChildren() - 1; i >= 0; i--)
      49                 :    2377783 :         processing_stack.push_back(current[i]);
      50                 :            :     }
      51                 :            :     else
      52                 :            :     {
      53                 :    2363216 :       result << current;
      54                 :            :     }
      55                 :    2813838 :   }
      56                 :     436055 :   Node resultNode = result;
      57         [ +  - ]:     872110 :   Trace("bv-rewrite") << "RewriteRule<ConcatFlatten>(" << resultNode << ")"
      58                 :     436055 :                       << std::endl;
      59                 :     872110 :   return resultNode;
      60                 :     436055 : }
      61                 :            : 
      62                 :            : /* -------------------------------------------------------------------------- */
      63                 :            : 
      64                 :            : template <>
      65                 :     847966 : inline bool RewriteRule<ConcatExtractMerge>::applies(TNode node)
      66                 :            : {
      67                 :     847966 :   return (node.getKind() == Kind::BITVECTOR_CONCAT);
      68                 :            : }
      69                 :            : 
      70                 :            : template <>
      71                 :     423747 : inline Node RewriteRule<ConcatExtractMerge>::apply(TNode node)
      72                 :            : {
      73         [ +  - ]:     847494 :   Trace("bv-rewrite") << "RewriteRule<ConcatExtractMerge>(" << node << ")"
      74                 :     423747 :                       << std::endl;
      75                 :            : 
      76                 :     423747 :   std::vector<Node> mergedExtracts;
      77                 :            : 
      78                 :     423747 :   Node current = node[0];
      79                 :     423747 :   bool mergeStarted = false;
      80                 :     423747 :   unsigned currentHigh = 0;
      81                 :     423747 :   unsigned currentLow = 0;
      82                 :            : 
      83         [ +  + ]:    2077699 :   for (size_t i = 1, end = node.getNumChildren(); i < end; ++i)
      84                 :            :   {
      85                 :            :     // The next candidate for merging
      86                 :    1653952 :     Node next = node[i];
      87                 :            :     // If the current is not an extract we just go to the next
      88         [ +  + ]:    1653952 :     if (current.getKind() != Kind::BITVECTOR_EXTRACT)
      89                 :            :     {
      90                 :    1482278 :       mergedExtracts.push_back(current);
      91                 :    1482278 :       current = next;
      92                 :    1482278 :       continue;
      93                 :            :     }
      94                 :            :     // If it is an extract and the first one, get the extract parameters
      95         [ +  + ]:     171674 :     else if (!mergeStarted)
      96                 :            :     {
      97                 :     171460 :       currentHigh = utils::getExtractHigh(current);
      98                 :     171460 :       currentLow = utils::getExtractLow(current);
      99                 :            :     }
     100                 :            : 
     101                 :            :     // If the next one can be merged, try to merge
     102                 :     171674 :     bool merged = false;
     103                 :     171674 :     if (next.getKind() == Kind::BITVECTOR_EXTRACT && current[0] == next[0])
     104                 :            :     {
     105                 :            :       // x[i : j] @ x[j - 1 : k] -> c x[i : k]
     106                 :      72386 :       unsigned nextHigh = utils::getExtractHigh(next);
     107                 :      72386 :       unsigned nextLow = utils::getExtractLow(next);
     108         [ +  + ]:      72386 :       if (nextHigh + 1 == currentLow)
     109                 :            :       {
     110                 :        380 :         currentLow = nextLow;
     111                 :        380 :         mergeStarted = true;
     112                 :        380 :         merged = true;
     113                 :            :       }
     114                 :            :     }
     115                 :            :     // If we haven't merged anything, add the previous merge and continue with
     116                 :            :     // the next
     117         [ +  + ]:     171674 :     if (!merged)
     118                 :            :     {
     119         [ +  + ]:     171294 :       if (!mergeStarted)
     120                 :     171246 :         mergedExtracts.push_back(current);
     121                 :            :       else
     122                 :         48 :         mergedExtracts.push_back(
     123                 :         96 :             utils::mkExtract(current[0], currentHigh, currentLow));
     124                 :     171294 :       current = next;
     125                 :     171294 :       mergeStarted = false;
     126                 :            :     }
     127         [ +  + ]:    1653952 :   }
     128                 :            : 
     129                 :            :   // Add the last child
     130         [ +  + ]:     423747 :   if (!mergeStarted)
     131                 :     423581 :     mergedExtracts.push_back(current);
     132                 :            :   else
     133                 :        166 :     mergedExtracts.push_back(
     134                 :        332 :         utils::mkExtract(current[0], currentHigh, currentLow));
     135                 :            : 
     136                 :            :   // Return the result
     137                 :     847494 :   return utils::mkConcat(mergedExtracts);
     138                 :     423747 : }
     139                 :            : 
     140                 :            : /* -------------------------------------------------------------------------- */
     141                 :            : 
     142                 :            : template <>
     143                 :     847544 : inline bool RewriteRule<ConcatConstantMerge>::applies(TNode node)
     144                 :            : {
     145                 :     847544 :   return node.getKind() == Kind::BITVECTOR_CONCAT;
     146                 :            : }
     147                 :            : 
     148                 :            : template <>
     149                 :     423535 : inline Node RewriteRule<ConcatConstantMerge>::apply(TNode node)
     150                 :            : {
     151         [ +  - ]:     847070 :   Trace("bv-rewrite") << "RewriteRule<ConcatConstantMerge>(" << node << ")"
     152                 :     423535 :                       << std::endl;
     153                 :            : 
     154                 :     423535 :   std::vector<Node> mergedConstants;
     155         [ +  + ]:    2453086 :   for (unsigned i = 0, end = node.getNumChildren(); i < end;)
     156                 :            :   {
     157         [ +  + ]:    2029551 :     if (node[i].getKind() != Kind::CONST_BITVECTOR)
     158                 :            :     {
     159                 :            :       // If not a constant, just add it
     160                 :    1733585 :       mergedConstants.push_back(node[i]);
     161                 :    1733585 :       ++i;
     162                 :            :     }
     163                 :            :     else
     164                 :            :     {
     165                 :            :       // Find the longest sequence of constants
     166                 :     295966 :       unsigned j = i + 1;
     167         [ +  + ]:     343414 :       while (j < end)
     168                 :            :       {
     169         [ +  + ]:     262671 :         if (node[j].getKind() != Kind::CONST_BITVECTOR)
     170                 :            :         {
     171                 :     215223 :           break;
     172                 :            :         }
     173                 :            :         else
     174                 :            :         {
     175                 :      47448 :           ++j;
     176                 :            :         }
     177                 :            :       }
     178                 :            :       // Append all the constants
     179                 :     295966 :       BitVector current = node[i].getConst<BitVector>();
     180         [ +  + ]:     343414 :       for (unsigned k = i + 1; k < j; ++k)
     181                 :            :       {
     182                 :      47448 :         current = current.concat(node[k].getConst<BitVector>());
     183                 :            :       }
     184                 :            :       // Add the new merged constant
     185                 :     295966 :       NodeManager* nm = node.getNodeManager();
     186                 :     295966 :       mergedConstants.push_back(utils::mkConst(nm, current));
     187                 :     295966 :       i = j;
     188                 :     295966 :     }
     189                 :            :   }
     190                 :            : 
     191         [ +  - ]:     847070 :   Trace("bv-rewrite") << "RewriteRule<ConcatConstantMerge>(" << node << ") => "
     192 [ -  + ][ -  - ]:     423535 :                       << utils::mkConcat(mergedConstants) << std::endl;
     193                 :            : 
     194                 :     847070 :   return utils::mkConcat(mergedConstants);
     195                 :     423535 : }
     196                 :            : 
     197                 :            : /* -------------------------------------------------------------------------- */
     198                 :            : 
     199                 :            : template <>
     200                 :    2289777 : inline bool RewriteRule<ExtractWhole>::applies(TNode node)
     201                 :            : {
     202         [ +  + ]:    2289777 :   if (node.getKind() != Kind::BITVECTOR_EXTRACT) return false;
     203                 :     445276 :   unsigned length = utils::getSize(node[0]);
     204                 :     445276 :   unsigned extractHigh = utils::getExtractHigh(node);
     205         [ +  + ]:     445276 :   if (extractHigh != length - 1) return false;
     206                 :     221855 :   unsigned extractLow = utils::getExtractLow(node);
     207         [ +  + ]:     221855 :   if (extractLow != 0) return false;
     208                 :      45726 :   return true;
     209                 :            : }
     210                 :            : 
     211                 :            : template <>
     212                 :      34001 : inline Node RewriteRule<ExtractWhole>::apply(TNode node)
     213                 :            : {
     214         [ +  - ]:      68002 :   Trace("bv-rewrite") << "RewriteRule<ExtractWhole>(" << node << ")"
     215                 :      34001 :                       << std::endl;
     216                 :      34001 :   return node[0];
     217                 :            : }
     218                 :            : 
     219                 :            : /* -------------------------------------------------------------------------- */
     220                 :            : 
     221                 :            : template <>
     222                 :     233830 : inline bool RewriteRule<ExtractConstant>::applies(TNode node)
     223                 :            : {
     224         [ +  + ]:     233830 :   if (node.getKind() != Kind::BITVECTOR_EXTRACT) return false;
     225         [ +  + ]:     222668 :   if (node[0].getKind() != Kind::CONST_BITVECTOR) return false;
     226                 :      65474 :   return true;
     227                 :            : }
     228                 :            : 
     229                 :            : template <>
     230                 :      32737 : inline Node RewriteRule<ExtractConstant>::apply(TNode node)
     231                 :            : {
     232         [ +  - ]:      65474 :   Trace("bv-rewrite") << "RewriteRule<ExtractConstant>(" << node << ")"
     233                 :      32737 :                       << std::endl;
     234                 :      32737 :   Node child = node[0];
     235                 :      32737 :   BitVector childValue = child.getConst<BitVector>();
     236                 :      32737 :   NodeManager* nm = node.getNodeManager();
     237                 :            :   return utils::mkConst(nm,
     238                 :      65474 :                         childValue.extract(utils::getExtractHigh(node),
     239                 :      65474 :                                            utils::getExtractLow(node)));
     240                 :      32737 : }
     241                 :            : 
     242                 :            : /* -------------------------------------------------------------------------- */
     243                 :            : 
     244                 :            : template <>
     245                 :     252369 : inline bool RewriteRule<ExtractConcat>::applies(TNode node)
     246                 :            : {
     247                 :            :   // Trace("bv-rewrite") << "RewriteRule<ExtractConcat>(" << node << ")" <<
     248                 :            :   // std::endl;
     249         [ +  + ]:     252369 :   if (node.getKind() != Kind::BITVECTOR_EXTRACT) return false;
     250         [ +  + ]:     251875 :   if (node[0].getKind() != Kind::BITVECTOR_CONCAT) return false;
     251                 :      45712 :   return true;
     252                 :            : }
     253                 :            : 
     254                 :            : template <>
     255                 :      22796 : inline Node RewriteRule<ExtractConcat>::apply(TNode node)
     256                 :            : {
     257         [ +  - ]:      45592 :   Trace("bv-rewrite") << "RewriteRule<ExtractConcat>(" << node << ")"
     258                 :      22796 :                       << std::endl;
     259                 :      22796 :   int extract_high = utils::getExtractHigh(node);
     260                 :      22796 :   int extract_low = utils::getExtractLow(node);
     261                 :            : 
     262                 :      22796 :   std::vector<Node> resultChildren;
     263                 :            : 
     264                 :      22796 :   Node concat = node[0];
     265 [ +  + ][ +  + ]:      70765 :   for (int i = concat.getNumChildren() - 1; i >= 0 && extract_high >= 0; i--)
     266                 :            :   {
     267                 :      47969 :     Node concatChild = concat[i];
     268                 :      47969 :     int concatChildSize = utils::getSize(concatChild);
     269         [ +  + ]:      47969 :     if (extract_low < concatChildSize)
     270                 :            :     {
     271                 :      43910 :       int extract_start = extract_low < 0 ? 0 : extract_low;
     272                 :      43910 :       int extract_end =
     273         [ +  + ]:      43910 :           extract_high < concatChildSize ? extract_high : concatChildSize - 1;
     274                 :      43910 :       resultChildren.push_back(
     275                 :      87820 :           utils::mkExtract(concatChild, extract_end, extract_start));
     276                 :            :     }
     277                 :      47969 :     extract_low -= concatChildSize;
     278                 :      47969 :     extract_high -= concatChildSize;
     279                 :      47969 :   }
     280                 :            : 
     281                 :      22796 :   std::reverse(resultChildren.begin(), resultChildren.end());
     282                 :            : 
     283                 :      45592 :   return utils::mkConcat(resultChildren);
     284                 :      22796 : }
     285                 :            : 
     286                 :            : /* -------------------------------------------------------------------------- */
     287                 :            : 
     288                 :            : template <>
     289                 :      75548 : inline bool RewriteRule<ExtractExtract>::applies(TNode node)
     290                 :            : {
     291         [ -  + ]:      75548 :   if (node.getKind() != Kind::BITVECTOR_EXTRACT) return false;
     292         [ +  + ]:      75548 :   if (node[0].getKind() != Kind::BITVECTOR_EXTRACT) return false;
     293                 :       3700 :   return true;
     294                 :            : }
     295                 :            : 
     296                 :            : template <>
     297                 :       1850 : inline Node RewriteRule<ExtractExtract>::apply(TNode node)
     298                 :            : {
     299         [ +  - ]:       3700 :   Trace("bv-rewrite") << "RewriteRule<ExtractExtract>(" << node << ")"
     300                 :       1850 :                       << std::endl;
     301                 :            : 
     302                 :            :   // x[i:j][k:l] ~>  x[k+j:l+j]
     303                 :       1850 :   uint32_t j = 0;
     304                 :       3700 :   Node child = node[0];
     305                 :            :   do
     306                 :            :   {
     307                 :       1850 :     j += utils::getExtractLow(child);
     308                 :       1850 :     child = child[0];
     309         [ -  + ]:       1850 :   } while (child.getKind() == Kind::BITVECTOR_EXTRACT);
     310                 :            : 
     311                 :       1850 :   uint32_t k = utils::getExtractHigh(node);
     312                 :       1850 :   uint32_t l = utils::getExtractLow(node);
     313                 :       1850 :   Node result = utils::mkExtract(child, k + j, l + j);
     314                 :       3700 :   return result;
     315                 :       1850 : }
     316                 :            : 
     317                 :            : /* -------------------------------------------------------------------------- */
     318                 :            : 
     319                 :            : template <>
     320                 :    1068759 : inline bool RewriteRule<FailEq>::applies(TNode node)
     321                 :            : {
     322                 :            :   // Trace("bv-rewrite") << "RewriteRule<FailEq>(" << node << ")" << std::endl;
     323         [ -  + ]:    1068759 :   if (node.getKind() != Kind::EQUAL) return false;
     324         [ +  + ]:    1068759 :   if (node[0].getKind() != Kind::CONST_BITVECTOR) return false;
     325         [ +  + ]:     436459 :   if (node[1].getKind() != Kind::CONST_BITVECTOR) return false;
     326                 :     100526 :   return node[0] != node[1];
     327                 :            : }
     328                 :            : 
     329                 :            : template <>
     330                 :      46803 : inline Node RewriteRule<FailEq>::apply(TNode node)
     331                 :            : {
     332                 :      46803 :   return utils::mkFalse(node.getNodeManager());
     333                 :            : }
     334                 :            : 
     335                 :            : /* -------------------------------------------------------------------------- */
     336                 :            : 
     337                 :            : template <>
     338                 :    1048561 : inline bool RewriteRule<SimplifyEq>::applies(TNode node)
     339                 :            : {
     340         [ +  + ]:    1048561 :   if (node.getKind() != Kind::EQUAL) return false;
     341                 :    1001758 :   return node[0] == node[1];
     342                 :            : }
     343                 :            : 
     344                 :            : template <>
     345                 :      26605 : inline Node RewriteRule<SimplifyEq>::apply(TNode node)
     346                 :            : {
     347         [ +  - ]:      26605 :   Trace("bv-rewrite") << "RewriteRule<SimplifyEq>(" << node << ")" << std::endl;
     348                 :      26605 :   return utils::mkTrue(node.getNodeManager());
     349                 :            : }
     350                 :            : 
     351                 :            : /* -------------------------------------------------------------------------- */
     352                 :            : 
     353                 :            : template <>
     354                 :    1125078 : inline bool RewriteRule<ReflexivityEq>::applies(TNode node)
     355                 :            : {
     356                 :    1125078 :   return (node.getKind() == Kind::EQUAL && node[0] > node[1]);
     357                 :            : }
     358                 :            : 
     359                 :            : template <>
     360                 :     103122 : inline Node RewriteRule<ReflexivityEq>::apply(TNode node)
     361                 :            : {
     362         [ +  - ]:     206244 :   Trace("bv-rewrite") << "RewriteRule<ReflexivityEq>(" << node << ")"
     363                 :     103122 :                       << std::endl;
     364                 :     206244 :   Node res = node[1].eqNode(node[0]);
     365                 :     103122 :   return res;
     366                 :            : }
     367                 :            : 
     368                 :            : }  // namespace bv
     369                 :            : }  // namespace theory
     370                 :            : }  // namespace cvc5::internal
     371                 :            : #endif

Generated by: LCOV version 1.14