LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/preprocessing/util - ite_utilities.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 488 1070 45.6 %
Date: 2026-03-09 11:40:42 Functions: 47 74 63.5 %
Branches: 266 651 40.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                 :            :  * Simplifications for ITE expressions.
      11                 :            :  *
      12                 :            :  * This module implements preprocessing phases designed to simplify ITE
      13                 :            :  * expressions.  Based on:
      14                 :            :  * Kim, Somenzi, Jin.  Efficient Term-ITE Conversion for SMT.  FMCAD 2009.
      15                 :            :  * Burch, Jerry.  Techniques for Verifying Superscalar Microprocessors.  DAC
      16                 :            :  *'96
      17                 :            :  */
      18                 :            : #include "preprocessing/util/ite_utilities.h"
      19                 :            : 
      20                 :            : #include <utility>
      21                 :            : 
      22                 :            : #include "expr/skolem_manager.h"
      23                 :            : #include "preprocessing/assertion_pipeline.h"
      24                 :            : #include "preprocessing/passes/rewrite.h"
      25                 :            : #include "theory/theory.h"
      26                 :            : #include "util/rational.h"
      27                 :            : 
      28                 :            : using namespace std;
      29                 :            : namespace cvc5::internal {
      30                 :            : namespace preprocessing {
      31                 :            : namespace util {
      32                 :            : 
      33                 :            : namespace ite {
      34                 :            : 
      35                 :     118726 : inline static bool isTermITE(TNode e)
      36                 :            : {
      37 [ +  + ][ +  + ]:     118726 :   return (e.getKind() == Kind::ITE && !e.getType().isBoolean());
         [ +  + ][ -  - ]
      38                 :            : }
      39                 :            : 
      40                 :     207839 : inline static bool triviallyContainsNoTermITEs(TNode e)
      41                 :            : {
      42 [ +  + ][ +  + ]:     207839 :   return e.isConst() || e.isVar();
      43                 :            : }
      44                 :            : 
      45                 :       5258 : static bool isTheoryAtom(TNode a)
      46                 :            : {
      47                 :            :   using namespace kind;
      48 [ +  - ][ +  + ]:       5258 :   switch (a.getKind())
      49                 :            :   {
      50                 :        109 :     case Kind::EQUAL:
      51                 :        109 :     case Kind::DISTINCT: return !(a[0].getType().isBoolean());
      52                 :            : 
      53                 :            :     /* from uf */
      54                 :          0 :     case Kind::APPLY_UF: return a.getType().isBoolean();
      55                 :         44 :     case Kind::CARDINALITY_CONSTRAINT:
      56                 :            :     case Kind::DIVISIBLE:
      57                 :            :     case Kind::LT:
      58                 :            :     case Kind::LEQ:
      59                 :            :     case Kind::GT:
      60                 :            :     case Kind::GEQ:
      61                 :            :     case Kind::IS_INTEGER:
      62                 :            :     case Kind::BITVECTOR_COMP:
      63                 :            :     case Kind::BITVECTOR_ULT:
      64                 :            :     case Kind::BITVECTOR_ULE:
      65                 :            :     case Kind::BITVECTOR_UGT:
      66                 :            :     case Kind::BITVECTOR_UGE:
      67                 :            :     case Kind::BITVECTOR_SLT:
      68                 :            :     case Kind::BITVECTOR_SLE:
      69                 :            :     case Kind::BITVECTOR_SGT:
      70                 :         44 :     case Kind::BITVECTOR_SGE: return true;
      71                 :       5105 :     default: return false;
      72                 :            :   }
      73                 :            : }
      74                 :            : 
      75                 :            : struct CTIVStackElement
      76                 :            : {
      77                 :            :   TNode curr;
      78                 :            :   unsigned pos;
      79                 :            :   CTIVStackElement() : curr(), pos(0) {}
      80                 :      99325 :   CTIVStackElement(TNode c) : curr(c), pos(0) {}
      81                 :            : }; /* CTIVStackElement */
      82                 :            : 
      83                 :            : }  // namespace ite
      84                 :            : 
      85                 :      50669 : ITEUtilities::ITEUtilities(Env& env)
      86                 :            :     : EnvObj(env),
      87                 :      50669 :       d_containsVisitor(new ContainsTermITEVisitor()),
      88                 :      50669 :       d_compressor(NULL),
      89                 :      50669 :       d_simplifier(NULL),
      90                 :      50669 :       d_careSimp(NULL)
      91                 :            : {
      92 [ -  + ][ -  + ]:      50669 :   Assert(d_containsVisitor != NULL);
                 [ -  - ]
      93                 :      50669 : }
      94                 :            : 
      95                 :      50324 : ITEUtilities::~ITEUtilities()
      96                 :            : {
      97         [ +  + ]:      50324 :   if (d_simplifier != NULL)
      98                 :            :   {
      99         [ +  - ]:          1 :     delete d_simplifier;
     100                 :            :   }
     101         [ +  + ]:      50324 :   if (d_compressor != NULL)
     102                 :            :   {
     103         [ +  - ]:          1 :     delete d_compressor;
     104                 :            :   }
     105         [ -  + ]:      50324 :   if (d_careSimp != NULL)
     106                 :            :   {
     107         [ -  - ]:          0 :     delete d_careSimp;
     108                 :            :   }
     109                 :      50324 : }
     110                 :            : 
     111                 :          1 : Node ITEUtilities::simpITE(TNode assertion)
     112                 :            : {
     113         [ +  - ]:          1 :   if (d_simplifier == NULL)
     114                 :            :   {
     115                 :          1 :     d_simplifier = new ITESimplifier(d_env, d_containsVisitor.get());
     116                 :            :   }
     117                 :          1 :   return d_simplifier->simpITE(assertion);
     118                 :            : }
     119                 :            : 
     120                 :          5 : bool ITEUtilities::simpIteDidALotOfWorkHeuristic() const
     121                 :            : {
     122         [ +  + ]:          5 :   if (d_simplifier == NULL)
     123                 :            :   {
     124                 :          4 :     return false;
     125                 :            :   }
     126                 :            :   else
     127                 :            :   {
     128                 :          1 :     return d_simplifier->doneALotOfWorkHeuristic();
     129                 :            :   }
     130                 :            : }
     131                 :            : 
     132                 :            : /* returns false if an assertion is discovered to be equal to false. */
     133                 :          1 : bool ITEUtilities::compress(AssertionPipeline* assertionsToPreprocess)
     134                 :            : {
     135         [ +  - ]:          1 :   if (d_compressor == NULL)
     136                 :            :   {
     137                 :          1 :     d_compressor = new ITECompressor(d_env, d_containsVisitor.get());
     138                 :            :   }
     139                 :          1 :   return d_compressor->compress(assertionsToPreprocess);
     140                 :            : }
     141                 :            : 
     142                 :          0 : Node ITEUtilities::simplifyWithCare(TNode e)
     143                 :            : {
     144         [ -  - ]:          0 :   if (d_careSimp == NULL)
     145                 :            :   {
     146                 :          0 :     d_careSimp = new ITECareSimplifier(nodeManager());
     147                 :            :   }
     148                 :          0 :   return d_careSimp->simplifyWithCare(e);
     149                 :            : }
     150                 :            : 
     151                 :          0 : void ITEUtilities::clear()
     152                 :            : {
     153         [ -  - ]:          0 :   if (d_simplifier != NULL)
     154                 :            :   {
     155                 :          0 :     d_simplifier->clearSimpITECaches();
     156                 :            :   }
     157         [ -  - ]:          0 :   if (d_compressor != NULL)
     158                 :            :   {
     159                 :          0 :     d_compressor->garbageCollect();
     160                 :            :   }
     161         [ -  - ]:          0 :   if (d_careSimp != NULL)
     162                 :            :   {
     163                 :          0 :     d_careSimp->clear();
     164                 :            :   }
     165                 :          0 :   d_containsVisitor->garbageCollect();
     166                 :          0 : }
     167                 :            : 
     168                 :            : /** ContainsTermITEVisitor. */
     169                 :      85214 : ContainsTermITEVisitor::ContainsTermITEVisitor() : d_cache() {}
     170                 :      84869 : ContainsTermITEVisitor::~ContainsTermITEVisitor() {}
     171                 :      37329 : bool ContainsTermITEVisitor::containsTermITE(TNode e)
     172                 :            : {
     173                 :            :   /* throughout execution skip through NOT nodes. */
     174         [ -  + ]:      37329 :   e = (e.getKind() == Kind::NOT) ? e[0] : e;
     175         [ +  + ]:      37329 :   if (ite::triviallyContainsNoTermITEs(e))
     176                 :            :   {
     177                 :      11575 :     return false;
     178                 :            :   }
     179                 :            : 
     180                 :      25754 :   NodeBoolMap::const_iterator end = d_cache.end();
     181                 :      25754 :   NodeBoolMap::const_iterator tmp_it = d_cache.find(e);
     182         [ +  + ]:      25754 :   if (tmp_it != end)
     183                 :            :   {
     184                 :       1167 :     return (*tmp_it).second;
     185                 :            :   }
     186                 :            : 
     187                 :      24587 :   bool foundTermIte = false;
     188                 :      24587 :   std::vector<ite::CTIVStackElement> stack;
     189                 :      24587 :   stack.push_back(ite::CTIVStackElement(e));
     190 [ +  + ][ +  + ]:     292437 :   while (!foundTermIte && !stack.empty())
                 [ +  + ]
     191                 :            :   {
     192                 :     267850 :     ite::CTIVStackElement& top = stack.back();
     193                 :     267850 :     TNode curr = top.curr;
     194         [ +  + ]:     267850 :     if (top.pos >= curr.getNumChildren())
     195                 :            :     {
     196                 :            :       // all of the children have been visited
     197                 :            :       // no term ites were found
     198                 :      97340 :       d_cache[curr] = false;
     199                 :      97340 :       stack.pop_back();
     200                 :            :     }
     201                 :            :     else
     202                 :            :     {
     203                 :            :       // this is someone's child
     204                 :     170510 :       TNode child = curr[top.pos];
     205         [ +  + ]:     170510 :       child = (child.getKind() == Kind::NOT) ? child[0] : child;
     206                 :     170510 :       ++top.pos;
     207         [ +  + ]:     170510 :       if (ite::triviallyContainsNoTermITEs(child))
     208                 :            :       {
     209                 :            :         // skip
     210                 :            :       }
     211                 :            :       else
     212                 :            :       {
     213                 :      76351 :         tmp_it = d_cache.find(child);
     214         [ +  + ]:      76351 :         if (tmp_it != end)
     215                 :            :         {
     216                 :       1613 :           foundTermIte = (*tmp_it).second;
     217                 :            :         }
     218                 :            :         else
     219                 :            :         {
     220                 :      74738 :           stack.push_back(ite::CTIVStackElement(child));
     221                 :      74738 :           foundTermIte = ite::isTermITE(child);
     222                 :            :         }
     223                 :            :       }
     224                 :     170510 :     }
     225                 :     267850 :   }
     226         [ +  + ]:      24587 :   if (foundTermIte)
     227                 :            :   {
     228         [ +  + ]:       3512 :     while (!stack.empty())
     229                 :            :     {
     230                 :       1985 :       TNode curr = stack.back().curr;
     231                 :       1985 :       stack.pop_back();
     232                 :       1985 :       d_cache[curr] = true;
     233                 :       1985 :     }
     234                 :            :   }
     235                 :      24587 :   return foundTermIte;
     236                 :      24587 : }
     237                 :          0 : void ContainsTermITEVisitor::garbageCollect() { d_cache.clear(); }
     238                 :            : 
     239                 :            : /** IncomingArcCounter. */
     240                 :          1 : IncomingArcCounter::IncomingArcCounter(bool skipVars, bool skipConstants)
     241                 :          1 :     : d_reachCount(), d_skipVariables(skipVars), d_skipConstants(skipConstants)
     242                 :            : {
     243                 :          1 : }
     244                 :          1 : IncomingArcCounter::~IncomingArcCounter() {}
     245                 :            : 
     246                 :          1 : void IncomingArcCounter::computeReachability(
     247                 :            :     const std::vector<Node>& assertions)
     248                 :            : {
     249                 :          1 :   std::vector<TNode> tovisit(assertions.begin(), assertions.end());
     250                 :            : 
     251         [ +  + ]:     114525 :   while (!tovisit.empty())
     252                 :            :   {
     253                 :     114524 :     TNode back = tovisit.back();
     254                 :     114524 :     tovisit.pop_back();
     255                 :            : 
     256                 :     114524 :     bool skip = false;
     257    [ +  + ][ + ]:     114524 :     switch (back.getMetaKind())
     258                 :            :     {
     259                 :        306 :       case kind::metakind::CONSTANT: skip = d_skipConstants; break;
     260                 :        210 :       case kind::metakind::VARIABLE: skip = d_skipVariables; break;
     261                 :     114008 :       default: break;
     262                 :            :     }
     263                 :            : 
     264         [ +  + ]:     114524 :     if (skip)
     265                 :            :     {
     266                 :        516 :       continue;
     267                 :            :     }
     268         [ +  + ]:     114008 :     if (d_reachCount.find(back) != d_reachCount.end())
     269                 :            :     {
     270                 :     106422 :       d_reachCount[back] = 1 + d_reachCount[back];
     271                 :            :     }
     272                 :            :     else
     273                 :            :     {
     274                 :       7586 :       d_reachCount[back] = 1;
     275         [ +  + ]:     122106 :       for (TNode::iterator cit = back.begin(), end = back.end(); cit != end;
     276                 :     114520 :            ++cit)
     277                 :            :       {
     278                 :     114520 :         tovisit.push_back(*cit);
     279                 :            :       }
     280                 :            :     }
     281         [ +  + ]:     114524 :   }
     282                 :          1 : }
     283                 :            : 
     284                 :          2 : void IncomingArcCounter::clear() { d_reachCount.clear(); }
     285                 :            : 
     286                 :            : /** ITECompressor. */
     287                 :          1 : ITECompressor::ITECompressor(Env& env, ContainsTermITEVisitor* contains)
     288                 :            :     : EnvObj(env),
     289                 :          1 :       d_contains(contains),
     290                 :          1 :       d_assertions(NULL),
     291                 :          1 :       d_incoming(true, true),
     292                 :          2 :       d_statistics(env.getStatisticsRegistry())
     293                 :            : {
     294 [ -  + ][ -  + ]:          1 :   Assert(d_contains != NULL);
                 [ -  - ]
     295                 :            : 
     296                 :          1 :   d_true = nodeManager()->mkConst<bool>(true);
     297                 :          1 :   d_false = nodeManager()->mkConst<bool>(false);
     298                 :          1 : }
     299                 :            : 
     300                 :          2 : ITECompressor::~ITECompressor() { reset(); }
     301                 :            : 
     302                 :          2 : void ITECompressor::reset()
     303                 :            : {
     304                 :          2 :   d_incoming.clear();
     305                 :          2 :   d_compressed.clear();
     306                 :          2 : }
     307                 :            : 
     308                 :          0 : void ITECompressor::garbageCollect() { reset(); }
     309                 :            : 
     310                 :          1 : ITECompressor::Statistics::Statistics(StatisticsRegistry& reg)
     311                 :          1 :     : d_compressCalls(reg.registerInt("ite-simp::compressCalls")),
     312                 :          1 :       d_skolemsAdded(reg.registerInt("ite-simp::skolems"))
     313                 :            : {
     314                 :          1 : }
     315                 :            : 
     316                 :       1720 : Node ITECompressor::push_back_boolean(Node original, Node compressed)
     317                 :            : {
     318                 :       1720 :   Node rewritten = rewrite(compressed);
     319                 :            :   // There is a bug if the rewritter takes a pure boolean expression
     320                 :            :   // and changes its theory
     321         [ -  + ]:       1720 :   if (rewritten.isConst())
     322                 :            :   {
     323                 :          0 :     d_compressed[compressed] = rewritten;
     324                 :          0 :     d_compressed[original] = rewritten;
     325                 :          0 :     d_compressed[rewritten] = rewritten;
     326                 :          0 :     return rewritten;
     327                 :            :   }
     328         [ -  + ]:       1720 :   else if (d_compressed.find(rewritten) != d_compressed.end())
     329                 :            :   {
     330                 :          0 :     Node res = d_compressed[rewritten];
     331                 :          0 :     d_compressed[original] = res;
     332                 :          0 :     d_compressed[compressed] = res;
     333                 :          0 :     return res;
     334                 :          0 :   }
     335                 :       5160 :   else if (rewritten.isVar()
     336 [ +  - ][ +  + ]:       1720 :            || (rewritten.getKind() == Kind::NOT && rewritten[0].isVar()))
         [ +  + ][ +  + ]
         [ +  + ][ -  - ]
     337                 :            :   {
     338                 :        511 :     d_compressed[original] = rewritten;
     339                 :        511 :     d_compressed[compressed] = rewritten;
     340                 :        511 :     d_compressed[rewritten] = rewritten;
     341                 :        511 :     return rewritten;
     342                 :            :   }
     343                 :            :   else
     344                 :            :   {
     345                 :       1209 :     NodeManager* nm = nodeManager();
     346                 :       2418 :     Node skolem = NodeManager::mkDummySkolem("compress", nm->booleanType());
     347                 :       1209 :     d_compressed[rewritten] = skolem;
     348                 :       1209 :     d_compressed[original] = skolem;
     349                 :       1209 :     d_compressed[compressed] = skolem;
     350                 :            : 
     351                 :       1209 :     Node iff = skolem.eqNode(rewritten);
     352                 :       1209 :     d_assertions->push_back(iff);
     353                 :       1209 :     ++(d_statistics.d_skolemsAdded);
     354                 :       1209 :     return skolem;
     355                 :       1209 :   }
     356                 :       1720 : }
     357                 :            : 
     358                 :       7109 : bool ITECompressor::multipleParents(TNode c)
     359                 :            : {
     360                 :       7109 :   return d_incoming.lookupIncoming(c) >= 2;
     361                 :            : }
     362                 :            : 
     363                 :       1920 : Node ITECompressor::compressBooleanITEs(Node toCompress)
     364                 :            : {
     365 [ -  + ][ -  + ]:       1920 :   Assert(toCompress.getKind() == Kind::ITE);
                 [ -  - ]
     366 [ -  + ][ -  + ]:       1920 :   Assert(toCompress.getType().isBoolean());
                 [ -  - ]
     367                 :            : 
     368                 :       1920 :   if (!(toCompress[1] == d_false || toCompress[2] == d_false))
     369                 :            :   {
     370                 :       1920 :     Node cmpCnd = compressBoolean(toCompress[0]);
     371         [ -  + ]:       1920 :     if (cmpCnd.isConst())
     372                 :            :     {
     373         [ -  - ]:          0 :       Node branch = (cmpCnd == d_true) ? toCompress[1] : toCompress[2];
     374                 :          0 :       Node res = compressBoolean(branch);
     375                 :          0 :       d_compressed[toCompress] = res;
     376                 :          0 :       return res;
     377                 :          0 :     }
     378                 :            :     else
     379                 :            :     {
     380                 :       1920 :       Node cmpThen = compressBoolean(toCompress[1]);
     381                 :       1920 :       Node cmpElse = compressBoolean(toCompress[2]);
     382                 :       1920 :       Node newIte = cmpCnd.iteNode(cmpThen, cmpElse);
     383         [ +  + ]:       1920 :       if (multipleParents(toCompress))
     384                 :            :       {
     385                 :        534 :         return push_back_boolean(toCompress, newIte);
     386                 :            :       }
     387                 :            :       else
     388                 :            :       {
     389                 :       1386 :         return newIte;
     390                 :            :       }
     391                 :       1920 :     }
     392                 :       1920 :   }
     393                 :            : 
     394                 :          0 :   NodeBuilder nb(nodeManager(), Kind::AND);
     395                 :          0 :   Node curr = toCompress;
     396                 :          0 :   while (curr.getKind() == Kind::ITE
     397                 :          0 :          && (curr[1] == d_false || curr[2] == d_false)
     398                 :          0 :          && (!multipleParents(curr) || curr == toCompress))
     399                 :            :   {
     400                 :          0 :     bool negateCnd = (curr[1] == d_false);
     401                 :          0 :     Node compressCnd = compressBoolean(curr[0]);
     402         [ -  - ]:          0 :     if (compressCnd.isConst())
     403                 :            :     {
     404         [ -  - ]:          0 :       if (compressCnd.getConst<bool>() == negateCnd)
     405                 :            :       {
     406                 :          0 :         return push_back_boolean(toCompress, d_false);
     407                 :            :       }
     408                 :            :       else
     409                 :            :       {
     410                 :            :         // equivalent to true don't push back
     411                 :            :       }
     412                 :            :     }
     413                 :            :     else
     414                 :            :     {
     415         [ -  - ]:          0 :       Node pb = negateCnd ? compressCnd.notNode() : compressCnd;
     416                 :          0 :       nb << pb;
     417                 :          0 :     }
     418         [ -  - ]:          0 :     curr = negateCnd ? curr[2] : curr[1];
     419         [ -  - ]:          0 :   }
     420                 :          0 :   Assert(toCompress != curr);
     421                 :            : 
     422                 :          0 :   nb << compressBoolean(curr);
     423         [ -  - ]:          0 :   Node res = nb.getNumChildren() == 1 ? nb[0] : (Node)nb;
     424                 :          0 :   return push_back_boolean(toCompress, res);
     425                 :          0 : }
     426                 :            : 
     427                 :       1122 : Node ITECompressor::compressTerm(Node toCompress)
     428                 :            : {
     429 [ +  + ][ +  + ]:       1122 :   if (toCompress.isConst() || toCompress.isVar())
                 [ +  + ]
     430                 :            :   {
     431                 :        513 :     return toCompress;
     432                 :            :   }
     433                 :            : 
     434         [ +  + ]:        609 :   if (d_compressed.find(toCompress) != d_compressed.end())
     435                 :            :   {
     436                 :        201 :     return d_compressed[toCompress];
     437                 :            :   }
     438         [ +  + ]:        408 :   if (toCompress.getKind() == Kind::ITE)
     439                 :            :   {
     440                 :        324 :     Node cmpCnd = compressBoolean(toCompress[0]);
     441         [ -  + ]:        324 :     if (cmpCnd.isConst())
     442                 :            :     {
     443         [ -  - ]:          0 :       Node branch = (cmpCnd == d_true) ? toCompress[1] : toCompress[2];
     444                 :          0 :       Node res = compressTerm(branch);
     445                 :          0 :       d_compressed[toCompress] = res;
     446                 :          0 :       return res;
     447                 :          0 :     }
     448                 :            :     else
     449                 :            :     {
     450                 :        324 :       Node cmpThen = compressTerm(toCompress[1]);
     451                 :        324 :       Node cmpElse = compressTerm(toCompress[2]);
     452                 :        324 :       Node newIte = cmpCnd.iteNode(cmpThen, cmpElse);
     453                 :        324 :       d_compressed[toCompress] = newIte;
     454                 :        324 :       return newIte;
     455                 :        324 :     }
     456                 :        324 :   }
     457                 :            : 
     458                 :         84 :   NodeBuilder nb(nodeManager(), toCompress.getKind());
     459                 :            : 
     460         [ -  + ]:         84 :   if (toCompress.getMetaKind() == kind::metakind::PARAMETERIZED)
     461                 :            :   {
     462                 :          0 :     nb << (toCompress.getOperator());
     463                 :            :   }
     464                 :         84 :   for (Node::iterator it = toCompress.begin(), end = toCompress.end();
     465         [ +  + ]:        252 :        it != end;
     466                 :        168 :        ++it)
     467                 :            :   {
     468                 :        168 :     nb << compressTerm(*it);
     469                 :            :   }
     470                 :         84 :   Node compressed = (Node)nb;
     471         [ +  + ]:         84 :   if (multipleParents(toCompress))
     472                 :            :   {
     473                 :         13 :     d_compressed[toCompress] = compressed;
     474                 :            :   }
     475                 :         84 :   return compressed;
     476                 :         84 : }
     477                 :            : 
     478                 :     113402 : Node ITECompressor::compressBoolean(Node toCompress)
     479                 :            : {
     480 [ +  + ][ -  + ]:     113402 :   if (toCompress.isConst() || toCompress.isVar())
                 [ +  + ]
     481                 :            :   {
     482                 :          3 :     return toCompress;
     483                 :            :   }
     484         [ +  + ]:     113399 :   if (d_compressed.find(toCompress) != d_compressed.end())
     485                 :            :   {
     486                 :     106221 :     return d_compressed[toCompress];
     487                 :            :   }
     488         [ +  + ]:       7178 :   else if (toCompress.getKind() == Kind::ITE)
     489                 :            :   {
     490                 :       1920 :     return compressBooleanITEs(toCompress);
     491                 :            :   }
     492                 :            :   else
     493                 :            :   {
     494                 :       5258 :     bool ta = ite::isTheoryAtom(toCompress);
     495                 :       5258 :     NodeBuilder nb(nodeManager(), toCompress.getKind());
     496         [ -  + ]:       5258 :     if (toCompress.getMetaKind() == kind::metakind::PARAMETERIZED)
     497                 :            :     {
     498                 :          0 :       nb << (toCompress.getOperator());
     499                 :            :     }
     500                 :       5258 :     for (Node::iterator it = toCompress.begin(), end = toCompress.end();
     501         [ +  + ]:     112878 :          it != end;
     502                 :     107620 :          ++it)
     503                 :            :     {
     504                 :     214934 :       Node pb = (ta) ? compressTerm(*it) : compressBoolean(*it);
     505                 :     107620 :       nb << pb;
     506                 :     107620 :     }
     507                 :       5258 :     Node compressed = nb;
     508 [ +  + ][ +  + ]:       5258 :     if (ta || multipleParents(toCompress))
         [ +  + ][ +  + ]
                 [ -  - ]
     509                 :            :     {
     510                 :       1186 :       return push_back_boolean(toCompress, compressed);
     511                 :            :     }
     512                 :            :     else
     513                 :            :     {
     514                 :       4072 :       return compressed;
     515                 :            :     }
     516                 :       5258 :   }
     517                 :            : }
     518                 :            : 
     519                 :          1 : bool ITECompressor::compress(AssertionPipeline* assertionsToPreprocess)
     520                 :            : {
     521                 :          1 :   reset();
     522                 :            : 
     523                 :          1 :   d_assertions = assertionsToPreprocess;
     524                 :          1 :   d_incoming.computeReachability(assertionsToPreprocess->ref());
     525                 :            : 
     526                 :          1 :   ++(d_statistics.d_compressCalls);
     527                 :          1 :   verbose(2) << "Computed reachability" << endl;
     528                 :            : 
     529                 :          1 :   bool nofalses = true;
     530                 :          1 :   const std::vector<Node>& assertions = assertionsToPreprocess->ref();
     531                 :          1 :   size_t original_size = assertions.size();
     532                 :          1 :   verbose(2) << "compressing " << original_size << endl;
     533 [ +  + ][ +  - ]:          5 :   for (size_t i = 0; i < original_size && nofalses; ++i)
     534                 :            :   {
     535                 :          4 :     Node assertion = assertions[i];
     536                 :          4 :     Node compressed = compressBoolean(assertion);
     537                 :          4 :     Node rewritten = rewrite(compressed);
     538                 :            :     // replace
     539                 :          4 :     assertionsToPreprocess->replace(i, rewritten);
     540 [ -  + ][ -  + ]:          4 :     Assert(!d_contains->containsTermITE(rewritten));
                 [ -  - ]
     541                 :            : 
     542                 :          4 :     nofalses = (rewritten != d_false);
     543                 :          4 :   }
     544                 :            : 
     545                 :          1 :   d_assertions = NULL;
     546                 :            : 
     547                 :          1 :   return nofalses;
     548                 :            : }
     549                 :            : 
     550                 :          1 : TermITEHeightCounter::TermITEHeightCounter() : d_termITEHeight() {}
     551                 :            : 
     552                 :          1 : TermITEHeightCounter::~TermITEHeightCounter() {}
     553                 :            : 
     554                 :          1 : void TermITEHeightCounter::clear() { d_termITEHeight.clear(); }
     555                 :            : 
     556                 :          0 : size_t TermITEHeightCounter::cache_size() const
     557                 :            : {
     558                 :          0 :   return d_termITEHeight.size();
     559                 :            : }
     560                 :            : 
     561                 :            : namespace ite {
     562                 :            : struct TITEHStackElement
     563                 :            : {
     564                 :            :   TNode curr;
     565                 :            :   unsigned pos;
     566                 :            :   uint32_t maxChildHeight;
     567                 :            :   TITEHStackElement() : curr(), pos(0), maxChildHeight(0) {}
     568                 :          0 :   TITEHStackElement(TNode c) : curr(c), pos(0), maxChildHeight(0) {}
     569                 :            : };
     570                 :            : } /* namespace ite */
     571                 :            : 
     572                 :          0 : uint32_t TermITEHeightCounter::termITEHeight(TNode e)
     573                 :            : {
     574         [ -  - ]:          0 :   if (ite::triviallyContainsNoTermITEs(e))
     575                 :            :   {
     576                 :          0 :     return 0;
     577                 :            :   }
     578                 :            : 
     579                 :          0 :   NodeCountMap::const_iterator end = d_termITEHeight.end();
     580                 :          0 :   NodeCountMap::const_iterator tmp_it = d_termITEHeight.find(e);
     581         [ -  - ]:          0 :   if (tmp_it != end)
     582                 :            :   {
     583                 :          0 :     return (*tmp_it).second;
     584                 :            :   }
     585                 :            : 
     586                 :          0 :   uint32_t returnValue = 0;
     587                 :            :   // This is initially 0 as the very first call this is included in the max,
     588                 :            :   // but this has no effect.
     589                 :          0 :   std::vector<ite::TITEHStackElement> stack;
     590                 :          0 :   stack.push_back(ite::TITEHStackElement(e));
     591         [ -  - ]:          0 :   while (!stack.empty())
     592                 :            :   {
     593                 :          0 :     ite::TITEHStackElement& top = stack.back();
     594                 :          0 :     top.maxChildHeight = std::max(top.maxChildHeight, returnValue);
     595                 :          0 :     TNode curr = top.curr;
     596         [ -  - ]:          0 :     if (top.pos >= curr.getNumChildren())
     597                 :            :     {
     598                 :            :       // done with the current node
     599         [ -  - ]:          0 :       returnValue = top.maxChildHeight + (ite::isTermITE(curr) ? 1 : 0);
     600                 :          0 :       d_termITEHeight[curr] = returnValue;
     601                 :          0 :       stack.pop_back();
     602                 :          0 :       continue;
     603                 :            :     }
     604                 :            :     else
     605                 :            :     {
     606                 :          0 :       if (top.pos == 0 && curr.getKind() == Kind::ITE)
     607                 :            :       {
     608                 :          0 :         ++top.pos;
     609                 :          0 :         returnValue = 0;
     610                 :          0 :         continue;
     611                 :            :       }
     612                 :            :       // this is someone's child
     613                 :          0 :       TNode child = curr[top.pos];
     614                 :          0 :       ++top.pos;
     615         [ -  - ]:          0 :       if (ite::triviallyContainsNoTermITEs(child))
     616                 :            :       {
     617                 :          0 :         returnValue = 0;
     618                 :            :       }
     619                 :            :       else
     620                 :            :       {
     621                 :          0 :         tmp_it = d_termITEHeight.find(child);
     622         [ -  - ]:          0 :         if (tmp_it != end)
     623                 :            :         {
     624                 :          0 :           returnValue = (*tmp_it).second;
     625                 :            :         }
     626                 :            :         else
     627                 :            :         {
     628                 :          0 :           stack.push_back(ite::TITEHStackElement(child));
     629                 :            :         }
     630                 :            :       }
     631                 :          0 :     }
     632         [ -  - ]:          0 :   }
     633                 :          0 :   return returnValue;
     634                 :          0 : }
     635                 :            : 
     636                 :          1 : ITESimplifier::ITESimplifier(Env& env, ContainsTermITEVisitor* contains)
     637                 :            :     : EnvObj(env),
     638                 :          1 :       d_containsVisitor(contains),
     639                 :          1 :       d_termITEHeight(),
     640                 :          1 :       d_constantLeaves(),
     641                 :          1 :       d_allocatedConstantLeaves(),
     642                 :          1 :       d_citeEqConstApplications(0),
     643                 :          1 :       d_constantIteEqualsConstantCache(),
     644                 :          1 :       d_replaceOverCache(),
     645                 :          1 :       d_replaceOverTermIteCache(),
     646                 :          1 :       d_leavesConstCache(),
     647                 :          1 :       d_simpConstCache(),
     648                 :          1 :       d_simpContextCache(),
     649                 :          1 :       d_simpITECache(),
     650                 :          3 :       d_statistics(env.getStatisticsRegistry())
     651                 :            : {
     652 [ -  + ][ -  + ]:          1 :   Assert(d_containsVisitor != NULL);
                 [ -  - ]
     653                 :          1 :   d_true = nodeManager()->mkConst<bool>(true);
     654                 :          1 :   d_false = nodeManager()->mkConst<bool>(false);
     655                 :          1 : }
     656                 :            : 
     657                 :          2 : ITESimplifier::~ITESimplifier()
     658                 :            : {
     659                 :          1 :   clearSimpITECaches();
     660 [ -  + ][ -  + ]:          1 :   Assert(d_constantLeaves.empty());
     661 [ -  + ][ -  + ]:          1 :   Assert(d_allocatedConstantLeaves.empty());
     662                 :          2 : }
     663                 :            : 
     664                 :        156 : bool ITESimplifier::leavesAreConst(TNode e)
     665                 :            : {
     666                 :        156 :   return leavesAreConst(e, d_env.theoryOf(e));
     667                 :            : }
     668                 :            : 
     669                 :          1 : void ITESimplifier::clearSimpITECaches()
     670                 :            : {
     671                 :          1 :   verbose(2) << "clear ite caches " << endl;
     672         [ +  + ]:        756 :   for (size_t i = 0, N = d_allocatedConstantLeaves.size(); i < N; ++i)
     673                 :            :   {
     674                 :        755 :     NodeVec* curr = d_allocatedConstantLeaves[i];
     675         [ +  - ]:        755 :     delete curr;
     676                 :            :   }
     677                 :          1 :   d_citeEqConstApplications = 0;
     678                 :          1 :   d_constantLeaves.clear();
     679                 :          1 :   d_allocatedConstantLeaves.clear();
     680                 :          1 :   d_termITEHeight.clear();
     681                 :          1 :   d_constantIteEqualsConstantCache.clear();
     682                 :          1 :   d_replaceOverCache.clear();
     683                 :          1 :   d_replaceOverTermIteCache.clear();
     684                 :          1 :   d_simpITECache.clear();
     685                 :          1 :   d_simpVars.clear();
     686                 :          1 :   d_simpConstCache.clear();
     687                 :          1 :   d_leavesConstCache.clear();
     688                 :          1 :   d_simpContextCache.clear();
     689                 :          1 : }
     690                 :            : 
     691                 :          1 : bool ITESimplifier::doneALotOfWorkHeuristic() const
     692                 :            : {
     693                 :            :   static const size_t SIZE_BOUND = 1000;
     694                 :          1 :   verbose(2) << "d_citeEqConstApplications size " << d_citeEqConstApplications
     695                 :          1 :          << endl;
     696                 :          1 :   return (d_citeEqConstApplications > SIZE_BOUND);
     697                 :            : }
     698                 :            : 
     699                 :          1 : ITESimplifier::Statistics::Statistics(StatisticsRegistry& reg)
     700                 :            :     : d_maxNonConstantsFolded(
     701                 :          1 :         reg.registerInt("ite-simp::maxNonConstantsFolded")),
     702                 :          1 :       d_unexpected(reg.registerInt("ite-simp::unexpected")),
     703                 :          1 :       d_unsimplified(reg.registerInt("ite-simp::unsimplified")),
     704                 :          1 :       d_exactMatchFold(reg.registerInt("ite-simp::exactMatchFold")),
     705                 :          1 :       d_binaryPredFold(reg.registerInt("ite-simp::binaryPredFold")),
     706                 :          1 :       d_specialEqualityFolds(reg.registerInt("ite-simp::specialEqualityFolds")),
     707                 :          1 :       d_simpITEVisits(reg.registerInt("ite-simp::simpITE.visits")),
     708                 :          1 :       d_numBranches(0),
     709                 :          1 :       d_numFalseBranches(0),
     710                 :          1 :       d_itesMade(0),
     711                 :          1 :       d_instance(0),
     712                 :          1 :       d_inSmaller(reg.registerHistogram<uint32_t>("ite-simp::inSmaller"))
     713                 :            : {
     714                 :          1 : }
     715                 :            : 
     716                 :       1253 : bool ITESimplifier::isConstantIte(TNode e)
     717                 :            : {
     718         [ +  + ]:       1253 :   if (e.isConst())
     719                 :            :   {
     720                 :        573 :     return true;
     721                 :            :   }
     722         [ +  - ]:        680 :   else if (ite::isTermITE(e))
     723                 :            :   {
     724                 :        680 :     NodeVec* constants = computeConstantLeaves(e);
     725                 :        680 :     return constants != NULL;
     726                 :            :   }
     727                 :            :   else
     728                 :            :   {
     729                 :          0 :     return false;
     730                 :            :   }
     731                 :            : }
     732                 :            : 
     733                 :      43308 : ITESimplifier::NodeVec* ITESimplifier::computeConstantLeaves(TNode ite)
     734                 :            : {
     735 [ -  + ][ -  + ]:      43308 :   Assert(ite::isTermITE(ite));
                 [ -  - ]
     736                 :      43308 :   ConstantLeavesMap::const_iterator it = d_constantLeaves.find(ite);
     737                 :      43308 :   ConstantLeavesMap::const_iterator end = d_constantLeaves.end();
     738         [ +  + ]:      43308 :   if (it != end)
     739                 :            :   {
     740                 :      42446 :     return (*it).second;
     741                 :            :   }
     742                 :        862 :   TNode thenB = ite[1];
     743                 :        862 :   TNode elseB = ite[2];
     744                 :            : 
     745                 :            :   // special case 2 constant children
     746 [ +  + ][ +  + ]:        862 :   if (thenB.isConst() && elseB.isConst())
                 [ +  + ]
     747                 :            :   {
     748                 :        152 :     NodeVec* pair = new NodeVec(2);
     749                 :        152 :     d_allocatedConstantLeaves.push_back(pair);
     750                 :            : 
     751                 :        152 :     (*pair)[0] = std::min(thenB, elseB);
     752                 :        152 :     (*pair)[1] = std::max(thenB, elseB);
     753                 :        152 :     d_constantLeaves[ite] = pair;
     754                 :        152 :     return pair;
     755                 :            :   }
     756                 :            :   // At least 1 is an ITE
     757         [ +  + ]:       1029 :   if (!(thenB.isConst() || thenB.getKind() == Kind::ITE)
     758 [ +  + ][ +  + ]:       1029 :       || !(elseB.isConst() || elseB.getKind() == Kind::ITE))
         [ +  + ][ +  + ]
     759                 :            :   {
     760                 :            :     // Cannot be a termITE tree
     761                 :        107 :     d_constantLeaves[ite] = NULL;
     762                 :        107 :     return NULL;
     763                 :            :   }
     764                 :            : 
     765                 :            :   // At least 1 is not a constant
     766         [ +  + ]:        603 :   TNode definitelyITE = thenB.isConst() ? elseB : thenB;
     767         [ +  + ]:        603 :   TNode maybeITE = thenB.isConst() ? thenB : elseB;
     768                 :            : 
     769                 :        603 :   NodeVec* defChildren = computeConstantLeaves(definitelyITE);
     770         [ -  + ]:        603 :   if (defChildren == NULL)
     771                 :            :   {
     772                 :          0 :     d_constantLeaves[ite] = NULL;
     773                 :          0 :     return NULL;
     774                 :            :   }
     775                 :            : 
     776                 :        603 :   NodeVec scratch;
     777                 :        603 :   NodeVec* maybeChildren = NULL;
     778         [ +  + ]:        603 :   if (maybeITE.getKind() == Kind::ITE)
     779                 :            :   {
     780                 :        192 :     maybeChildren = computeConstantLeaves(maybeITE);
     781                 :            :   }
     782                 :            :   else
     783                 :            :   {
     784                 :        411 :     scratch.push_back(maybeITE);
     785                 :        411 :     maybeChildren = &scratch;
     786                 :            :   }
     787         [ -  + ]:        603 :   if (maybeChildren == NULL)
     788                 :            :   {
     789                 :          0 :     d_constantLeaves[ite] = NULL;
     790                 :          0 :     return NULL;
     791                 :            :   }
     792                 :            : 
     793                 :        603 :   NodeVec* both = new NodeVec(defChildren->size() + maybeChildren->size());
     794                 :        603 :   d_allocatedConstantLeaves.push_back(both);
     795                 :        603 :   NodeVec::iterator newEnd;
     796                 :        603 :   newEnd = std::set_union(defChildren->begin(),
     797                 :            :                           defChildren->end(),
     798                 :            :                           maybeChildren->begin(),
     799                 :            :                           maybeChildren->end(),
     800                 :            :                           both->begin());
     801                 :        603 :   both->resize(newEnd - both->begin());
     802                 :        603 :   d_constantLeaves[ite] = both;
     803                 :        603 :   return both;
     804                 :        862 : }
     805                 :            : 
     806                 :            : // This is uncached! Better for protoyping or getting limited size examples
     807                 :            : struct IteTreeSearchData
     808                 :            : {
     809                 :            :   set<Node> visited;
     810                 :            :   set<Node> constants;
     811                 :            :   set<Node> nonConstants;
     812                 :            :   int maxConstants;
     813                 :            :   int maxNonconstants;
     814                 :            :   int maxDepth;
     815                 :            :   bool failure;
     816                 :          0 :   IteTreeSearchData()
     817                 :          0 :       : maxConstants(-1), maxNonconstants(-1), maxDepth(-1), failure(false)
     818                 :            :   {
     819                 :          0 :   }
     820                 :            : };
     821                 :          0 : void iteTreeSearch(Node e, int depth, IteTreeSearchData& search)
     822                 :            : {
     823 [ -  - ][ -  - ]:          0 :   if (search.maxDepth >= 0 && depth > search.maxDepth)
     824                 :            :   {
     825                 :          0 :     search.failure = true;
     826                 :            :   }
     827         [ -  - ]:          0 :   if (search.failure)
     828                 :            :   {
     829                 :          0 :     return;
     830                 :            :   }
     831         [ -  - ]:          0 :   if (search.visited.find(e) != search.visited.end())
     832                 :            :   {
     833                 :          0 :     return;
     834                 :            :   }
     835                 :            :   else
     836                 :            :   {
     837                 :          0 :     search.visited.insert(e);
     838                 :            :   }
     839                 :            : 
     840         [ -  - ]:          0 :   if (e.isConst())
     841                 :            :   {
     842                 :          0 :     search.constants.insert(e);
     843                 :          0 :     if (search.maxConstants >= 0
     844 [ -  - ][ -  - ]:          0 :         && search.constants.size() > (unsigned)search.maxConstants)
                 [ -  - ]
     845                 :            :     {
     846                 :          0 :       search.failure = true;
     847                 :            :     }
     848                 :            :   }
     849         [ -  - ]:          0 :   else if (e.getKind() == Kind::ITE)
     850                 :            :   {
     851                 :          0 :     iteTreeSearch(e[1], depth + 1, search);
     852                 :          0 :     iteTreeSearch(e[2], depth + 1, search);
     853                 :            :   }
     854                 :            :   else
     855                 :            :   {
     856                 :          0 :     search.nonConstants.insert(e);
     857                 :          0 :     if (search.maxNonconstants >= 0
     858 [ -  - ][ -  - ]:          0 :         && search.nonConstants.size() > (unsigned)search.maxNonconstants)
                 [ -  - ]
     859                 :            :     {
     860                 :          0 :       search.failure = true;
     861                 :            :     }
     862                 :            :   }
     863                 :            : }
     864                 :            : 
     865                 :          0 : Node ITESimplifier::replaceOver(Node n, Node replaceWith, Node simpVar)
     866                 :            : {
     867         [ -  - ]:          0 :   if (n == simpVar)
     868                 :            :   {
     869                 :          0 :     return replaceWith;
     870                 :            :   }
     871         [ -  - ]:          0 :   else if (n.getNumChildren() == 0)
     872                 :            :   {
     873                 :          0 :     return n;
     874                 :            :   }
     875                 :          0 :   Assert(n.getNumChildren() > 0);
     876                 :          0 :   Assert(!n.isVar());
     877                 :            : 
     878                 :          0 :   pair<Node, Node> p = make_pair(n, replaceWith);
     879         [ -  - ]:          0 :   if (d_replaceOverCache.find(p) != d_replaceOverCache.end())
     880                 :            :   {
     881                 :          0 :     return d_replaceOverCache[p];
     882                 :            :   }
     883                 :            : 
     884                 :          0 :   NodeBuilder builder(nodeManager(), n.getKind());
     885         [ -  - ]:          0 :   if (n.getMetaKind() == kind::metakind::PARAMETERIZED)
     886                 :            :   {
     887                 :          0 :     builder << n.getOperator();
     888                 :            :   }
     889                 :          0 :   unsigned i = 0;
     890         [ -  - ]:          0 :   for (; i < n.getNumChildren(); ++i)
     891                 :            :   {
     892                 :          0 :     Node newChild = replaceOver(n[i], replaceWith, simpVar);
     893                 :          0 :     builder << newChild;
     894                 :          0 :   }
     895                 :            :   // Mark the substitution and continue
     896                 :          0 :   Node result = builder;
     897                 :          0 :   d_replaceOverCache[p] = result;
     898                 :          0 :   return result;
     899                 :          0 : }
     900                 :            : 
     901                 :          0 : Node ITESimplifier::replaceOverTermIte(Node e, Node simpAtom, Node simpVar)
     902                 :            : {
     903         [ -  - ]:          0 :   if (e.getKind() == Kind::ITE)
     904                 :            :   {
     905                 :          0 :     pair<Node, Node> p = make_pair(e, simpAtom);
     906         [ -  - ]:          0 :     if (d_replaceOverTermIteCache.find(p) != d_replaceOverTermIteCache.end())
     907                 :            :     {
     908                 :          0 :       return d_replaceOverTermIteCache[p];
     909                 :            :     }
     910                 :          0 :     Assert(!e.getType().isBoolean());
     911                 :          0 :     Node cnd = e[0];
     912                 :          0 :     Node newThen = replaceOverTermIte(e[1], simpAtom, simpVar);
     913                 :          0 :     Node newElse = replaceOverTermIte(e[2], simpAtom, simpVar);
     914                 :          0 :     Node newIte = cnd.iteNode(newThen, newElse);
     915                 :          0 :     d_replaceOverTermIteCache[p] = newIte;
     916                 :          0 :     return newIte;
     917                 :          0 :   }
     918                 :            :   else
     919                 :            :   {
     920                 :          0 :     return replaceOver(simpAtom, e, simpVar);
     921                 :            :   }
     922                 :            : }
     923                 :            : 
     924                 :          0 : Node ITESimplifier::attemptLiftEquality(TNode atom)
     925                 :            : {
     926         [ -  - ]:          0 :   if (atom.getKind() == Kind::EQUAL)
     927                 :            :   {
     928                 :          0 :     TNode left = atom[0];
     929                 :          0 :     TNode right = atom[1];
     930         [ -  - ]:          0 :     if ((left.getKind() == Kind::ITE || right.getKind() == Kind::ITE)
     931                 :          0 :         && !(left.getKind() == Kind::ITE && right.getKind() == Kind::ITE))
     932                 :            :     {
     933                 :            :       // exactly 1 is an ite
     934         [ -  - ]:          0 :       TNode ite = left.getKind() == Kind::ITE ? left : right;
     935         [ -  - ]:          0 :       TNode notIte = left.getKind() == Kind::ITE ? right : left;
     936                 :            : 
     937         [ -  - ]:          0 :       if (notIte == ite[1])
     938                 :            :       {
     939                 :          0 :         ++(d_statistics.d_exactMatchFold);
     940                 :          0 :         return ite[0].iteNode(d_true, notIte.eqNode(ite[2]));
     941                 :            :       }
     942         [ -  - ]:          0 :       else if (notIte == ite[2])
     943                 :            :       {
     944                 :          0 :         ++(d_statistics.d_exactMatchFold);
     945                 :          0 :         return ite[0].iteNode(notIte.eqNode(ite[1]), d_true);
     946                 :            :       }
     947                 :          0 :       if (notIte.isConst() && (ite[1].isConst() || ite[2].isConst()))
     948                 :            :       {
     949                 :          0 :         ++(d_statistics.d_exactMatchFold);
     950                 :          0 :         return ite[0].iteNode(notIte.eqNode(ite[1]), notIte.eqNode(ite[2]));
     951                 :            :       }
     952 [ -  - ][ -  - ]:          0 :     }
     953 [ -  - ][ -  - ]:          0 :   }
     954                 :            : 
     955                 :            :   // try a similar more relaxed version for non-equality operators
     956                 :          0 :   if (atom.getMetaKind() == kind::metakind::OPERATOR
     957                 :          0 :       && atom.getNumChildren() == 2 && !atom[1].getType().isBoolean())
     958                 :            :   {
     959                 :          0 :     TNode left = atom[0];
     960                 :          0 :     TNode right = atom[1];
     961         [ -  - ]:          0 :     if ((left.getKind() == Kind::ITE || right.getKind() == Kind::ITE)
     962                 :          0 :         && !(left.getKind() == Kind::ITE && right.getKind() == Kind::ITE))
     963                 :            :     {
     964                 :            :       // exactly 1 is an ite
     965                 :          0 :       bool leftIsIte = left.getKind() == Kind::ITE;
     966         [ -  - ]:          0 :       Node ite = leftIsIte ? left : right;
     967         [ -  - ]:          0 :       Node notIte = leftIsIte ? right : left;
     968                 :            : 
     969         [ -  - ]:          0 :       if (notIte.isConst())
     970                 :            :       {
     971                 :          0 :         IteTreeSearchData search;
     972                 :          0 :         search.maxNonconstants = 2;
     973                 :          0 :         iteTreeSearch(ite, 0, search);
     974         [ -  - ]:          0 :         if (!search.failure)
     975                 :            :         {
     976                 :          0 :           d_statistics.d_maxNonConstantsFolded.maxAssign(
     977                 :          0 :               search.nonConstants.size());
     978         [ -  - ]:          0 :           Trace("ite::simpite") << "used " << search.nonConstants.size()
     979                 :          0 :                                 << " nonconstants" << endl;
     980                 :          0 :           NodeManager* nm = nodeManager();
     981                 :          0 :           Node simpVar = getSimpVar(notIte.getType());
     982         [ -  - ]:          0 :           TNode newLeft = leftIsIte ? simpVar : notIte;
     983         [ -  - ]:          0 :           TNode newRight = leftIsIte ? notIte : simpVar;
     984                 :          0 :           Node newAtom = nm->mkNode(atom.getKind(), newLeft, newRight);
     985                 :            : 
     986                 :          0 :           ++(d_statistics.d_binaryPredFold);
     987                 :          0 :           return replaceOverTermIte(ite, newAtom, simpVar);
     988                 :          0 :         }
     989         [ -  - ]:          0 :       }
     990 [ -  - ][ -  - ]:          0 :     }
     991 [ -  - ][ -  - ]:          0 :   }
     992                 :            : 
     993                 :            :   // TODO "This is way too tailored. Must generalize!"
     994         [ -  - ]:          0 :   if (atom.getKind() == Kind::EQUAL && atom.getNumChildren() == 2
     995                 :          0 :       && ite::isTermITE(atom[0]) && atom[1].getKind() == Kind::MULT
     996                 :          0 :       && atom[1].getNumChildren() == 2 && atom[1][0].isConst()
     997                 :          0 :       && atom[1][0].getConst<Rational>().isNegativeOne()
     998                 :          0 :       && ite::isTermITE(atom[1][1])
     999                 :          0 :       && d_termITEHeight.termITEHeight(atom[0]) == 1
    1000                 :          0 :       && d_termITEHeight.termITEHeight(atom[1][1]) == 1
    1001                 :          0 :       && (atom[0][1].isConst() || atom[0][2].isConst())
    1002                 :          0 :       && (atom[1][1][1].isConst() || atom[1][1][2].isConst()))
    1003                 :            :   {
    1004                 :            :     // expand all 4 cases
    1005                 :            : 
    1006                 :          0 :     Node negOne = atom[1][0];
    1007                 :            : 
    1008                 :          0 :     Node lite = atom[0];
    1009                 :          0 :     Node lC = lite[0];
    1010                 :          0 :     Node lT = lite[1];
    1011                 :          0 :     Node lE = lite[2];
    1012                 :            : 
    1013                 :          0 :     NodeManager* nm = nodeManager();
    1014                 :          0 :     Node negRite = atom[1][1];
    1015                 :          0 :     Node rC = negRite[0];
    1016                 :          0 :     Node rT = nm->mkNode(Kind::MULT, negOne, negRite[1]);
    1017                 :          0 :     Node rE = nm->mkNode(Kind::MULT, negOne, negRite[2]);
    1018                 :            : 
    1019                 :            :     // (ite lC lT lE) = (ite rC rT rE)
    1020                 :            :     // (ite lc (= lT (ite rC rT rE) (= lE (ite rC rT rE))))
    1021                 :            :     // (ite lc (ite rC (= lT rT) (= lT rE))
    1022                 :            :     //         (ite rC (= lE rT) (= lE rE)))
    1023                 :            : 
    1024                 :          0 :     Node eqTT = lT.eqNode(rT);
    1025                 :          0 :     Node eqTE = lT.eqNode(rE);
    1026                 :          0 :     Node eqET = lE.eqNode(rT);
    1027                 :          0 :     Node eqEE = lE.eqNode(rE);
    1028                 :          0 :     Node thenLC = rC.iteNode(eqTT, eqTE);
    1029                 :          0 :     Node elseLC = rC.iteNode(eqET, eqEE);
    1030                 :          0 :     Node newIte = lC.iteNode(thenLC, elseLC);
    1031                 :            : 
    1032                 :          0 :     ++(d_statistics.d_specialEqualityFolds);
    1033                 :          0 :     return newIte;
    1034                 :          0 :   }
    1035                 :          0 :   return Node::null();
    1036                 :            : }
    1037                 :            : 
    1038                 :            : // Interesting classes of atoms:
    1039                 :            : // 2. Contains constants and 1 constant term ite
    1040                 :            : // 3. Contains 2 constant term ites
    1041                 :        729 : Node ITESimplifier::transformAtom(TNode atom)
    1042                 :            : {
    1043         [ -  + ]:        729 :   if (!d_containsVisitor->containsTermITE(atom))
    1044                 :            :   {
    1045                 :          0 :     if (atom.getKind() == Kind::EQUAL && atom[0].isConst() && atom[1].isConst())
    1046                 :            :     {
    1047                 :            :       // constant equality
    1048                 :          0 :       return nodeManager()->mkConst<bool>(atom[0] == atom[1]);
    1049                 :            :     }
    1050                 :          0 :     return Node::null();
    1051                 :            :   }
    1052                 :            :   else
    1053                 :            :   {
    1054                 :        729 :     Node acr = attemptConstantRemoval(atom);
    1055         [ +  + ]:        729 :     if (!acr.isNull())
    1056                 :            :     {
    1057                 :        573 :       return acr;
    1058                 :            :     }
    1059                 :            :     // Node ale = attemptLiftEquality(atom);
    1060                 :            :     // if(!ale.isNull()){
    1061                 :            :     //   //return ale;
    1062                 :            :     // }
    1063                 :        156 :     return Node::null();
    1064                 :        729 :   }
    1065                 :            : }
    1066                 :            : 
    1067                 :      67339 : Node ITESimplifier::constantIteEqualsConstant(TNode cite, TNode constant)
    1068                 :            : {
    1069                 :      67339 :   d_statistics.d_instance = 0;
    1070                 :      67339 :   ++(d_statistics.d_instance);
    1071         [ +  - ]:     134678 :   Trace("ite::constantIteEqualsConstant")
    1072                 :          0 :       << (d_statistics.d_instance) << "constantIteEqualsConstant(" << cite
    1073                 :      67339 :       << ", " << constant << ")" << endl;
    1074         [ +  + ]:      67339 :   if (cite.isConst())
    1075                 :            :   {
    1076         [ +  + ]:      22839 :     Node res = (cite == constant) ? d_true : d_false;
    1077         [ +  - ]:      45678 :     Trace("ite::constantIteEqualsConstant")
    1078                 :      22839 :         << (d_statistics.d_instance) << "->" << res << endl;
    1079                 :      22839 :     return res;
    1080                 :      22839 :   }
    1081                 :      44500 :   std::pair<Node, Node> pair = make_pair(cite, constant);
    1082                 :            : 
    1083                 :            :   NodePairMap::const_iterator eq_pos =
    1084                 :      44500 :       d_constantIteEqualsConstantCache.find(pair);
    1085         [ +  + ]:      44500 :   if (eq_pos != d_constantIteEqualsConstantCache.end())
    1086                 :            :   {
    1087         [ +  - ]:       5334 :     Trace("ite::constantIteEqualsConstant")
    1088                 :       2667 :         << (d_statistics.d_instance) << "->" << (*eq_pos).second << endl;
    1089                 :       2667 :     return (*eq_pos).second;
    1090                 :            :   }
    1091                 :            : 
    1092                 :      41833 :   ++d_citeEqConstApplications;
    1093                 :            : 
    1094                 :      41833 :   NodeVec* leaves = computeConstantLeaves(cite);
    1095 [ -  + ][ -  + ]:      41833 :   Assert(leaves != NULL);
                 [ -  - ]
    1096         [ +  + ]:      41833 :   if (std::binary_search(leaves->begin(), leaves->end(), constant))
    1097                 :            :   {
    1098         [ -  + ]:      33383 :     if (leaves->size() == 1)
    1099                 :            :     {
    1100                 :            :       // probably unreachable
    1101                 :          0 :       d_constantIteEqualsConstantCache[pair] = d_true;
    1102         [ -  - ]:          0 :       Trace("ite::constantIteEqualsConstant")
    1103                 :          0 :           << (d_statistics.d_instance) << "->" << d_true << endl;
    1104                 :          0 :       return d_true;
    1105                 :            :     }
    1106                 :            :     else
    1107                 :            :     {
    1108 [ -  + ][ -  + ]:      33383 :       Assert(cite.getKind() == Kind::ITE);
                 [ -  - ]
    1109                 :      33383 :       TNode cnd = cite[0];
    1110                 :      33383 :       TNode tB = cite[1];
    1111                 :      33383 :       TNode fB = cite[2];
    1112                 :      66766 :       Node tEqs = constantIteEqualsConstant(tB, constant);
    1113                 :      66766 :       Node fEqs = constantIteEqualsConstant(fB, constant);
    1114                 :      33383 :       Node boolIte = cnd.iteNode(tEqs, fEqs);
    1115 [ +  + ][ +  + ]:      33383 :       if (!(tEqs.isConst() || fEqs.isConst()))
                 [ +  + ]
    1116                 :            :       {
    1117                 :       1924 :         ++(d_statistics.d_numBranches);
    1118                 :            :       }
    1119 [ +  + ][ +  + ]:      33383 :       if (!(tEqs == d_false || fEqs == d_false))
                 [ +  + ]
    1120                 :            :       {
    1121                 :       2211 :         ++(d_statistics.d_numFalseBranches);
    1122                 :            :       }
    1123                 :      33383 :       ++(d_statistics.d_itesMade);
    1124                 :      33383 :       d_constantIteEqualsConstantCache[pair] = boolIte;
    1125                 :            :       // Trace("ite::constantIteEqualsConstant") << instance << "->" << boolIte
    1126                 :            :       // << endl;
    1127                 :      33383 :       return boolIte;
    1128                 :      33383 :     }
    1129                 :            :   }
    1130                 :            :   else
    1131                 :            :   {
    1132                 :       8450 :     d_constantIteEqualsConstantCache[pair] = d_false;
    1133         [ +  - ]:      16900 :     Trace("ite::constantIteEqualsConstant")
    1134                 :       8450 :         << (d_statistics.d_instance) << "->" << d_false << endl;
    1135                 :       8450 :     return d_false;
    1136                 :            :   }
    1137                 :      44500 : }
    1138                 :            : 
    1139                 :        573 : Node ITESimplifier::intersectConstantIte(TNode lcite, TNode rcite)
    1140                 :            : {
    1141                 :            :   // intersect the constant ite trees lcite and rcite
    1142                 :            : 
    1143 [ +  - ][ +  - ]:        573 :   if (lcite.isConst() || rcite.isConst())
                 [ +  - ]
    1144                 :            :   {
    1145                 :        573 :     bool lIsConst = lcite.isConst();
    1146         [ -  + ]:        573 :     TNode constant = lIsConst ? lcite : rcite;
    1147         [ -  + ]:        573 :     TNode cite = lIsConst ? rcite : lcite;
    1148                 :            : 
    1149                 :        573 :     (d_statistics.d_inSmaller) << 1;
    1150                 :        573 :     unsigned preItesMade = d_statistics.d_itesMade;
    1151                 :        573 :     unsigned preNumBranches = d_statistics.d_numBranches;
    1152                 :        573 :     unsigned preNumFalseBranches = d_statistics.d_numFalseBranches;
    1153                 :       1146 :     Node bterm = constantIteEqualsConstant(cite, constant);
    1154         [ +  - ]:       1146 :     Trace("intersectConstantIte")
    1155                 :          0 :         << ((d_statistics.d_numBranches) - preNumBranches) << " "
    1156                 :          0 :         << ((d_statistics.d_numFalseBranches) - preNumFalseBranches) << " "
    1157                 :        573 :         << ((d_statistics.d_itesMade) - preItesMade) << endl;
    1158                 :        573 :     return bterm;
    1159                 :        573 :   }
    1160                 :          0 :   Assert(lcite.getKind() == Kind::ITE);
    1161                 :          0 :   Assert(rcite.getKind() == Kind::ITE);
    1162                 :            : 
    1163                 :          0 :   NodeVec* leftValues = computeConstantLeaves(lcite);
    1164                 :          0 :   NodeVec* rightValues = computeConstantLeaves(rcite);
    1165                 :            : 
    1166                 :          0 :   uint32_t smaller = std::min(leftValues->size(), rightValues->size());
    1167                 :            : 
    1168                 :          0 :   (d_statistics.d_inSmaller) << smaller;
    1169                 :          0 :   NodeVec intersection(smaller, Node::null());
    1170                 :          0 :   NodeVec::iterator newEnd;
    1171                 :          0 :   newEnd = std::set_intersection(leftValues->begin(),
    1172                 :            :                                  leftValues->end(),
    1173                 :            :                                  rightValues->begin(),
    1174                 :            :                                  rightValues->end(),
    1175                 :            :                                  intersection.begin());
    1176                 :          0 :   intersection.resize(newEnd - intersection.begin());
    1177         [ -  - ]:          0 :   if (intersection.empty())
    1178                 :            :   {
    1179                 :          0 :     return d_false;
    1180                 :            :   }
    1181                 :            :   else
    1182                 :            :   {
    1183                 :          0 :     NodeBuilder nb(nodeManager(), Kind::OR);
    1184                 :          0 :     NodeVec::const_iterator it = intersection.begin(), end = intersection.end();
    1185         [ -  - ]:          0 :     for (; it != end; ++it)
    1186                 :            :     {
    1187                 :          0 :       Node inBoth = *it;
    1188                 :          0 :       Node lefteq = constantIteEqualsConstant(lcite, inBoth);
    1189                 :          0 :       Node righteq = constantIteEqualsConstant(rcite, inBoth);
    1190                 :          0 :       Node bothHold = lefteq.andNode(righteq);
    1191                 :          0 :       nb << bothHold;
    1192                 :          0 :     }
    1193         [ -  - ]:          0 :     Node result = (nb.getNumChildren() > 1) ? (Node)nb : nb[0];
    1194                 :          0 :     return result;
    1195                 :          0 :   }
    1196                 :          0 : }
    1197                 :            : 
    1198                 :          0 : Node ITESimplifier::attemptEagerRemoval(TNode atom)
    1199                 :            : {
    1200         [ -  - ]:          0 :   if (atom.getKind() == Kind::EQUAL)
    1201                 :            :   {
    1202                 :          0 :     TNode left = atom[0];
    1203                 :          0 :     TNode right = atom[1];
    1204                 :          0 :     if ((left.isConst() && right.getKind() == Kind::ITE && isConstantIte(right))
    1205                 :          0 :         || (right.isConst() && left.getKind() == Kind::ITE
    1206                 :          0 :             && isConstantIte(left)))
    1207                 :            :     {
    1208         [ -  - ]:          0 :       TNode constant = left.isConst() ? left : right;
    1209         [ -  - ]:          0 :       TNode cite = left.isConst() ? right : left;
    1210                 :            : 
    1211                 :          0 :       std::pair<Node, Node> pair = make_pair(cite, constant);
    1212                 :            :       NodePairMap::const_iterator eq_pos =
    1213                 :          0 :           d_constantIteEqualsConstantCache.find(pair);
    1214         [ -  - ]:          0 :       if (eq_pos != d_constantIteEqualsConstantCache.end())
    1215                 :            :       {
    1216                 :          0 :         Node ret = (*eq_pos).second;
    1217         [ -  - ]:          0 :         if (ret.isConst())
    1218                 :            :         {
    1219                 :          0 :           return ret;
    1220                 :            :         }
    1221                 :            :         else
    1222                 :            :         {
    1223                 :          0 :           return Node::null();
    1224                 :            :         }
    1225                 :          0 :       }
    1226                 :            : 
    1227                 :          0 :       NodeVec* leaves = computeConstantLeaves(cite);
    1228                 :          0 :       Assert(leaves != NULL);
    1229         [ -  - ]:          0 :       if (!std::binary_search(leaves->begin(), leaves->end(), constant))
    1230                 :            :       {
    1231                 :          0 :         d_constantIteEqualsConstantCache[pair] = d_false;
    1232                 :          0 :         return d_false;
    1233                 :            :       }
    1234 [ -  - ][ -  - ]:          0 :     }
                 [ -  - ]
    1235 [ -  - ][ -  - ]:          0 :   }
    1236                 :          0 :   return Node::null();
    1237                 :            : }
    1238                 :            : 
    1239                 :        729 : Node ITESimplifier::attemptConstantRemoval(TNode atom)
    1240                 :            : {
    1241         [ +  + ]:        729 :   if (atom.getKind() == Kind::EQUAL)
    1242                 :            :   {
    1243                 :        680 :     TNode left = atom[0];
    1244                 :        680 :     TNode right = atom[1];
    1245                 :        680 :     if (isConstantIte(left) && isConstantIte(right))
    1246                 :            :     {
    1247                 :        573 :       return intersectConstantIte(left, right);
    1248                 :            :     }
    1249 [ +  + ][ +  + ]:       1253 :   }
    1250                 :        156 :   return Node::null();
    1251                 :            : }
    1252                 :            : 
    1253                 :        528 : bool ITESimplifier::leavesAreConst(TNode e, theory::TheoryId tid)
    1254                 :            : {
    1255                 :        528 :   Assert((e.getKind() == Kind::ITE && !e.getType().isBoolean())
    1256                 :            :          || d_env.theoryOf(e) != theory::THEORY_BOOL);
    1257         [ +  + ]:        528 :   if (e.isConst())
    1258                 :            :   {
    1259                 :         16 :     return true;
    1260                 :            :   }
    1261                 :            : 
    1262                 :        512 :   unordered_map<Node, bool>::iterator it;
    1263                 :        512 :   it = d_leavesConstCache.find(e);
    1264         [ +  + ]:        512 :   if (it != d_leavesConstCache.end())
    1265                 :            :   {
    1266                 :        123 :     return (*it).second;
    1267                 :            :   }
    1268                 :            : 
    1269                 :        389 :   if (!containsTermITE(e) && theory::Theory::isLeafOf(e, tid))
    1270                 :            :   {
    1271                 :         33 :     d_leavesConstCache[e] = false;
    1272                 :         33 :     return false;
    1273                 :            :   }
    1274                 :            : 
    1275 [ -  + ][ -  + ]:        356 :   Assert(e.getNumChildren() > 0);
                 [ -  - ]
    1276                 :        356 :   size_t k = 0, sz = e.getNumChildren();
    1277                 :            : 
    1278         [ +  + ]:        356 :   if (e.getKind() == Kind::ITE)
    1279                 :            :   {
    1280                 :        161 :     k = 1;
    1281                 :            :   }
    1282                 :            : 
    1283         [ +  - ]:        372 :   for (; k < sz; ++k)
    1284                 :            :   {
    1285         [ +  + ]:        372 :     if (!leavesAreConst(e[k], tid))
    1286                 :            :     {
    1287                 :        356 :       d_leavesConstCache[e] = false;
    1288                 :        356 :       return false;
    1289                 :            :     }
    1290                 :            :   }
    1291                 :          0 :   d_leavesConstCache[e] = true;
    1292                 :          0 :   return true;
    1293                 :            : }
    1294                 :            : 
    1295                 :          0 : Node ITESimplifier::simpConstants(TNode simpContext,
    1296                 :            :                                   TNode iteNode,
    1297                 :            :                                   TNode simpVar)
    1298                 :            : {
    1299                 :          0 :   NodePairMap::iterator it;
    1300                 :          0 :   it = d_simpConstCache.find(pair<Node, Node>(simpContext, iteNode));
    1301         [ -  - ]:          0 :   if (it != d_simpConstCache.end())
    1302                 :            :   {
    1303                 :          0 :     return (*it).second;
    1304                 :            :   }
    1305                 :            : 
    1306         [ -  - ]:          0 :   if (iteNode.getKind() == Kind::ITE)
    1307                 :            :   {
    1308                 :          0 :     NodeBuilder builder(nodeManager(), Kind::ITE);
    1309                 :          0 :     builder << iteNode[0];
    1310                 :          0 :     unsigned i = 1;
    1311         [ -  - ]:          0 :     for (; i < iteNode.getNumChildren(); ++i)
    1312                 :            :     {
    1313                 :          0 :       Node n = simpConstants(simpContext, iteNode[i], simpVar);
    1314         [ -  - ]:          0 :       if (n.isNull())
    1315                 :            :       {
    1316                 :          0 :         return n;
    1317                 :            :       }
    1318                 :          0 :       builder << n;
    1319         [ -  - ]:          0 :     }
    1320                 :            :     // Mark the substitution and continue
    1321                 :          0 :     Node result = builder;
    1322                 :          0 :     result = rewrite(result);
    1323                 :          0 :     d_simpConstCache[pair<Node, Node>(simpContext, iteNode)] = result;
    1324                 :          0 :     return result;
    1325                 :          0 :   }
    1326                 :            : 
    1327         [ -  - ]:          0 :   if (!containsTermITE(iteNode))
    1328                 :            :   {
    1329                 :          0 :     Node n = rewrite(simpContext.substitute(simpVar, iteNode));
    1330                 :          0 :     d_simpConstCache[pair<Node, Node>(simpContext, iteNode)] = n;
    1331                 :          0 :     return n;
    1332                 :          0 :   }
    1333                 :            : 
    1334                 :          0 :   Node iteNode2;
    1335                 :          0 :   Node simpVar2;
    1336                 :          0 :   d_simpContextCache.clear();
    1337                 :          0 :   Node simpContext2 = createSimpContext(iteNode, iteNode2, simpVar2);
    1338         [ -  - ]:          0 :   if (!simpContext2.isNull())
    1339                 :            :   {
    1340                 :          0 :     Assert(!iteNode2.isNull());
    1341                 :          0 :     simpContext2 = simpContext.substitute(simpVar, simpContext2);
    1342                 :          0 :     Node n = simpConstants(simpContext2, iteNode2, simpVar2);
    1343         [ -  - ]:          0 :     if (n.isNull())
    1344                 :            :     {
    1345                 :          0 :       return n;
    1346                 :            :     }
    1347                 :          0 :     d_simpConstCache[pair<Node, Node>(simpContext, iteNode)] = n;
    1348                 :          0 :     return n;
    1349                 :          0 :   }
    1350                 :          0 :   return Node();
    1351                 :          0 : }
    1352                 :            : 
    1353                 :          0 : Node ITESimplifier::getSimpVar(TypeNode t)
    1354                 :            : {
    1355                 :          0 :   std::unordered_map<TypeNode, Node>::iterator it;
    1356                 :          0 :   it = d_simpVars.find(t);
    1357         [ -  - ]:          0 :   if (it != d_simpVars.end())
    1358                 :            :   {
    1359                 :          0 :     return (*it).second;
    1360                 :            :   }
    1361                 :          0 :   Node var = NodeManager::mkDummySkolem("iteSimp", t);
    1362                 :          0 :   d_simpVars[t] = var;
    1363                 :          0 :   return var;
    1364                 :          0 : }
    1365                 :            : 
    1366                 :          0 : Node ITESimplifier::createSimpContext(TNode c, Node& iteNode, Node& simpVar)
    1367                 :            : {
    1368                 :          0 :   NodeMap::iterator it;
    1369                 :          0 :   it = d_simpContextCache.find(c);
    1370         [ -  - ]:          0 :   if (it != d_simpContextCache.end())
    1371                 :            :   {
    1372                 :          0 :     return (*it).second;
    1373                 :            :   }
    1374                 :            : 
    1375         [ -  - ]:          0 :   if (!containsTermITE(c))
    1376                 :            :   {
    1377                 :          0 :     d_simpContextCache[c] = c;
    1378                 :          0 :     return c;
    1379                 :            :   }
    1380                 :            : 
    1381                 :          0 :   if (c.getKind() == Kind::ITE && !c.getType().isBoolean())
    1382                 :            :   {
    1383                 :            :     // Currently only support one ite node in a simp context
    1384                 :            :     // Return Null if more than one is found
    1385         [ -  - ]:          0 :     if (!iteNode.isNull())
    1386                 :            :     {
    1387                 :          0 :       return Node();
    1388                 :            :     }
    1389                 :          0 :     simpVar = getSimpVar(c.getType());
    1390         [ -  - ]:          0 :     if (simpVar.isNull())
    1391                 :            :     {
    1392                 :          0 :       return Node();
    1393                 :            :     }
    1394                 :          0 :     d_simpContextCache[c] = simpVar;
    1395                 :          0 :     iteNode = c;
    1396                 :          0 :     return simpVar;
    1397                 :            :   }
    1398                 :            : 
    1399                 :          0 :   NodeBuilder builder(nodeManager(), c.getKind());
    1400         [ -  - ]:          0 :   if (c.getMetaKind() == kind::metakind::PARAMETERIZED)
    1401                 :            :   {
    1402                 :          0 :     builder << c.getOperator();
    1403                 :            :   }
    1404                 :          0 :   unsigned i = 0;
    1405         [ -  - ]:          0 :   for (; i < c.getNumChildren(); ++i)
    1406                 :            :   {
    1407                 :          0 :     Node newChild = createSimpContext(c[i], iteNode, simpVar);
    1408         [ -  - ]:          0 :     if (newChild.isNull())
    1409                 :            :     {
    1410                 :          0 :       return newChild;
    1411                 :            :     }
    1412                 :          0 :     builder << newChild;
    1413         [ -  - ]:          0 :   }
    1414                 :            :   // Mark the substitution and continue
    1415                 :          0 :   Node result = builder;
    1416                 :          0 :   d_simpContextCache[c] = result;
    1417                 :          0 :   return result;
    1418                 :          0 : }
    1419                 :            : typedef std::unordered_set<Node> NodeSet;
    1420                 :          0 : void countReachable_(Node x, Kind k, NodeSet& visited, uint32_t& reached)
    1421                 :            : {
    1422         [ -  - ]:          0 :   if (visited.find(x) != visited.end())
    1423                 :            :   {
    1424                 :          0 :     return;
    1425                 :            :   }
    1426                 :          0 :   visited.insert(x);
    1427         [ -  - ]:          0 :   if (x.getKind() == k)
    1428                 :            :   {
    1429                 :          0 :     ++reached;
    1430                 :            :   }
    1431         [ -  - ]:          0 :   for (unsigned i = 0, N = x.getNumChildren(); i < N; ++i)
    1432                 :            :   {
    1433                 :          0 :     countReachable_(x[i], k, visited, reached);
    1434                 :            :   }
    1435                 :            : }
    1436                 :            : 
    1437                 :          0 : uint32_t countReachable(TNode x, Kind k)
    1438                 :            : {
    1439                 :          0 :   NodeSet visited;
    1440                 :          0 :   uint32_t reached = 0;
    1441                 :          0 :   countReachable_(x, k, visited, reached);
    1442                 :          0 :   return reached;
    1443                 :          0 : }
    1444                 :            : 
    1445                 :        729 : Node ITESimplifier::simpITEAtom(TNode atom)
    1446                 :            : {
    1447                 :            :   CVC5_UNUSED static int instance = 0;
    1448         [ +  - ]:        729 :   Trace("ite::atom") << "still simplifying " << (++instance) << endl;
    1449                 :        729 :   Node attempt = transformAtom(atom);
    1450         [ +  - ]:        729 :   Trace("ite::atom") << "  finished " << instance << endl;
    1451         [ +  + ]:        729 :   if (!attempt.isNull())
    1452                 :            :   {
    1453                 :        573 :     Node rewritten = rewrite(attempt);
    1454         [ +  - ]:       1146 :     Trace("ite::print-success")
    1455                 :          0 :         << instance << " "
    1456         [ -  - ]:        573 :         << "rewriting " << countReachable(rewritten, Kind::ITE) << " from "
    1457 [ -  + ][ -  + ]:        573 :         << countReachable(atom, Kind::ITE) << endl
                 [ -  - ]
    1458                 :          0 :         << "\t rewritten " << rewritten << endl
    1459                 :        573 :         << "\t input " << atom << endl;
    1460                 :        573 :     return rewritten;
    1461                 :        573 :   }
    1462                 :            : 
    1463         [ -  + ]:        156 :   if (leavesAreConst(atom))
    1464                 :            :   {
    1465                 :          0 :     Node iteNode;
    1466                 :          0 :     Node simpVar;
    1467                 :          0 :     d_simpContextCache.clear();
    1468                 :          0 :     Node simpContext = createSimpContext(atom, iteNode, simpVar);
    1469         [ -  - ]:          0 :     if (!simpContext.isNull())
    1470                 :            :     {
    1471         [ -  - ]:          0 :       if (iteNode.isNull())
    1472                 :            :       {
    1473                 :          0 :         Assert(leavesAreConst(simpContext) && !containsTermITE(simpContext));
    1474                 :          0 :         ++(d_statistics.d_unexpected);
    1475         [ -  - ]:          0 :         Trace("ite::simpite") << instance << " "
    1476                 :          0 :                               << "how about?" << atom << endl;
    1477         [ -  - ]:          0 :         Trace("ite::simpite") << instance << " "
    1478                 :          0 :                               << "\t" << simpContext << endl;
    1479                 :          0 :         return rewrite(simpContext);
    1480                 :            :       }
    1481                 :          0 :       Node n = simpConstants(simpContext, iteNode, simpVar);
    1482         [ -  - ]:          0 :       if (!n.isNull())
    1483                 :            :       {
    1484                 :          0 :         ++(d_statistics.d_unexpected);
    1485         [ -  - ]:          0 :         Trace("ite::simpite") << instance << " "
    1486                 :          0 :                               << "here?" << atom << endl;
    1487         [ -  - ]:          0 :         Trace("ite::simpite") << instance << " "
    1488                 :          0 :                               << "\t" << n << endl;
    1489                 :          0 :         return n;
    1490                 :            :       }
    1491         [ -  - ]:          0 :     }
    1492 [ -  - ][ -  - ]:          0 :   }
                 [ -  - ]
    1493         [ -  + ]:        156 :   if (TraceIsOn("ite::simpite"))
    1494                 :            :   {
    1495         [ -  - ]:          0 :     if (countReachable(atom, Kind::ITE) > 0)
    1496                 :            :     {
    1497         [ -  - ]:          0 :       Trace("ite::simpite") << instance << " "
    1498                 :          0 :                             << "remaining " << atom << endl;
    1499                 :            :     }
    1500                 :            :   }
    1501                 :        156 :   ++(d_statistics.d_unsimplified);
    1502                 :        156 :   return atom;
    1503                 :        729 : }
    1504                 :            : 
    1505                 :            : struct preprocess_stack_element
    1506                 :            : {
    1507                 :            :   TNode d_node;
    1508                 :            :   bool d_children_added;
    1509                 :       2454 :   preprocess_stack_element(TNode node) : d_node(node), d_children_added(false)
    1510                 :            :   {
    1511                 :       2454 :   }
    1512                 :            : }; /* struct preprocess_stack_element */
    1513                 :            : 
    1514                 :          1 : Node ITESimplifier::simpITE(TNode assertion)
    1515                 :            : {
    1516                 :            :   // Do a topological sort of the subexpressions and substitute them
    1517                 :          1 :   vector<preprocess_stack_element> toVisit;
    1518                 :          1 :   toVisit.push_back(assertion);
    1519                 :            : 
    1520         [ +  + ]:       4373 :   while (!toVisit.empty())
    1521                 :            :   {
    1522                 :            :     // cout << "call  " << call << " : " << iteration << endl;
    1523                 :            :     // The current node we are processing
    1524                 :       4372 :     preprocess_stack_element& stackHead = toVisit.back();
    1525                 :       4372 :     TNode current = stackHead.d_node;
    1526                 :            : 
    1527                 :            :     // If node has no ITE's or already in the cache we're done, pop from the
    1528                 :            :     // stack
    1529                 :      13641 :     if (current.getNumChildren() == 0
    1530 [ +  + ][ +  + ]:      10386 :         || (d_env.theoryOf(current) != theory::THEORY_BOOL
         [ +  + ][ -  - ]
    1531 [ +  + ][ +  + ]:       6014 :             && !containsTermITE(current)))
         [ +  + ][ -  - ]
    1532                 :            :     {
    1533                 :        525 :       d_simpITECache[current] = current;
    1534                 :        525 :       ++(d_statistics.d_simpITEVisits);
    1535                 :        525 :       toVisit.pop_back();
    1536                 :        525 :       continue;
    1537                 :            :     }
    1538                 :            : 
    1539                 :       3847 :     NodeMap::iterator find = d_simpITECache.find(current);
    1540         [ +  + ]:       3847 :     if (find != d_simpITECache.end())
    1541                 :            :     {
    1542                 :         11 :       toVisit.pop_back();
    1543                 :         11 :       continue;
    1544                 :            :     }
    1545                 :            : 
    1546                 :            :     // Not yet substituted, so process
    1547         [ +  + ]:       3836 :     if (stackHead.d_children_added)
    1548                 :            :     {
    1549                 :            :       // Children have been processed, so substitute
    1550                 :       1918 :       NodeBuilder builder(nodeManager(), current.getKind());
    1551         [ -  + ]:       1918 :       if (current.getMetaKind() == kind::metakind::PARAMETERIZED)
    1552                 :            :       {
    1553                 :          0 :         builder << current.getOperator();
    1554                 :            :       }
    1555         [ +  + ]:       6869 :       for (unsigned i = 0; i < current.getNumChildren(); ++i)
    1556                 :            :       {
    1557 [ -  + ][ -  + ]:       4951 :         Assert(d_simpITECache.find(current[i]) != d_simpITECache.end());
                 [ -  - ]
    1558                 :       4951 :         Node child = current[i];
    1559                 :       9902 :         Node childRes = d_simpITECache[current[i]];
    1560                 :       4951 :         builder << childRes;
    1561                 :       4951 :       }
    1562                 :            :       // Mark the substitution and continue
    1563                 :       1918 :       Node result = builder;
    1564                 :            : 
    1565                 :            :       // If this is an atom, we process it
    1566 [ +  + ][ -  - ]:       1918 :       if (d_env.theoryOf(result) != theory::THEORY_BOOL
    1567 [ +  + ][ +  + ]:       1918 :           && result.getType().isBoolean())
         [ +  + ][ +  - ]
                 [ -  - ]
    1568                 :            :       {
    1569                 :        729 :         result = simpITEAtom(result);
    1570                 :            :       }
    1571                 :            : 
    1572                 :            :       // if(current != result && result.isConst()){
    1573                 :            :       //   static int instance = 0;
    1574                 :            :       //   //cout << instance << " " << result << current << endl;
    1575                 :            :       // }
    1576                 :            : 
    1577                 :       1918 :       result = rewrite(result);
    1578                 :       1918 :       d_simpITECache[current] = result;
    1579                 :       1918 :       ++(d_statistics.d_simpITEVisits);
    1580                 :       1918 :       toVisit.pop_back();
    1581                 :       1918 :     }
    1582                 :            :     else
    1583                 :            :     {
    1584                 :            :       // Mark that we have added the children if any
    1585         [ +  - ]:       1918 :       if (current.getNumChildren() > 0)
    1586                 :            :       {
    1587                 :       1918 :         stackHead.d_children_added = true;
    1588                 :            :         // We need to add the children
    1589                 :       1918 :         for (TNode::iterator child_it = current.begin();
    1590         [ +  + ]:       6869 :              child_it != current.end();
    1591                 :       4951 :              ++child_it)
    1592                 :            :         {
    1593                 :       4951 :           TNode childNode = *child_it;
    1594                 :       4951 :           NodeMap::iterator childFind = d_simpITECache.find(childNode);
    1595         [ +  + ]:       4951 :           if (childFind == d_simpITECache.end())
    1596                 :            :           {
    1597                 :       2453 :             toVisit.push_back(childNode);
    1598                 :            :           }
    1599                 :       4951 :         }
    1600                 :            :       }
    1601                 :            :       else
    1602                 :            :       {
    1603                 :            :         // No children, so we're done
    1604                 :          0 :         d_simpITECache[current] = current;
    1605                 :          0 :         ++(d_statistics.d_simpITEVisits);
    1606                 :          0 :         toVisit.pop_back();
    1607                 :            :       }
    1608                 :            :     }
    1609         [ +  + ]:       4372 :   }
    1610                 :          2 :   return d_simpITECache[assertion];
    1611                 :          1 : }
    1612                 :            : 
    1613                 :          0 : ITECareSimplifier::ITECareSimplifier(NodeManager* nm) : d_careSetsOutstanding(0), d_usedSets()
    1614                 :            : {
    1615                 :          0 :   d_true = nm->mkConst<bool>(true);
    1616                 :          0 :   d_false = nm->mkConst<bool>(false);
    1617                 :          0 : }
    1618                 :            : 
    1619                 :          0 : ITECareSimplifier::~ITECareSimplifier()
    1620                 :            : {
    1621 [ -  - ][ -  - ]:          0 :   Assert(d_usedSets.empty());
    1622 [ -  - ][ -  - ]:          0 :   Assert(d_careSetsOutstanding == 0);
    1623                 :          0 : }
    1624                 :            : 
    1625                 :          0 : void ITECareSimplifier::clear()
    1626                 :            : {
    1627                 :          0 :   Assert(d_usedSets.empty());
    1628                 :          0 :   Assert(d_careSetsOutstanding == 0);
    1629                 :          0 : }
    1630                 :            : 
    1631                 :          0 : ITECareSimplifier::CareSetPtr ITECareSimplifier::getNewSet()
    1632                 :            : {
    1633         [ -  - ]:          0 :   if (d_usedSets.empty())
    1634                 :            :   {
    1635                 :          0 :     d_careSetsOutstanding++;
    1636                 :          0 :     return ITECareSimplifier::CareSetPtr::mkNew(*this);
    1637                 :            :   }
    1638                 :            :   else
    1639                 :            :   {
    1640                 :            :     ITECareSimplifier::CareSetPtr cs =
    1641                 :          0 :         ITECareSimplifier::CareSetPtr::recycle(d_usedSets.back());
    1642                 :          0 :     cs.getCareSet().clear();
    1643                 :          0 :     d_usedSets.pop_back();
    1644                 :          0 :     return cs;
    1645                 :          0 :   }
    1646                 :            : }
    1647                 :            : 
    1648                 :          0 : void ITECareSimplifier::updateQueue(CareMap& queue,
    1649                 :            :                                     TNode e,
    1650                 :            :                                     ITECareSimplifier::CareSetPtr& careSet)
    1651                 :            : {
    1652                 :          0 :   CareMap::iterator it = queue.find(e), iend = queue.end();
    1653         [ -  - ]:          0 :   if (it != iend)
    1654                 :            :   {
    1655                 :          0 :     set<Node>& cs2 = (*it).second.getCareSet();
    1656                 :          0 :     ITECareSimplifier::CareSetPtr csNew = getNewSet();
    1657                 :          0 :     set_intersection(careSet.getCareSet().begin(),
    1658                 :          0 :                      careSet.getCareSet().end(),
    1659                 :            :                      cs2.begin(),
    1660                 :            :                      cs2.end(),
    1661                 :          0 :                      inserter(csNew.getCareSet(), csNew.getCareSet().begin()));
    1662                 :          0 :     (*it).second = csNew;
    1663                 :          0 :   }
    1664                 :            :   else
    1665                 :            :   {
    1666                 :          0 :     queue[e] = careSet;
    1667                 :            :   }
    1668                 :          0 : }
    1669                 :            : 
    1670                 :          0 : Node ITECareSimplifier::substitute(TNode e,
    1671                 :            :                                    TNodeMap& substTable,
    1672                 :            :                                    TNodeMap& cache)
    1673                 :            : {
    1674                 :          0 :   TNodeMap::iterator it = cache.find(e), iend = cache.end();
    1675         [ -  - ]:          0 :   if (it != iend)
    1676                 :            :   {
    1677                 :          0 :     return it->second;
    1678                 :            :   }
    1679                 :            : 
    1680                 :            :   // do substitution?
    1681                 :          0 :   it = substTable.find(e);
    1682                 :          0 :   iend = substTable.end();
    1683         [ -  - ]:          0 :   if (it != iend)
    1684                 :            :   {
    1685                 :          0 :     Node result = substitute(it->second, substTable, cache);
    1686                 :          0 :     cache[e] = result;
    1687                 :          0 :     return result;
    1688                 :          0 :   }
    1689                 :            : 
    1690                 :          0 :   size_t sz = e.getNumChildren();
    1691         [ -  - ]:          0 :   if (sz == 0)
    1692                 :            :   {
    1693                 :          0 :     cache[e] = e;
    1694                 :          0 :     return e;
    1695                 :            :   }
    1696                 :            : 
    1697                 :          0 :   NodeBuilder builder(e.getNodeManager(), e.getKind());
    1698         [ -  - ]:          0 :   if (e.getMetaKind() == kind::metakind::PARAMETERIZED)
    1699                 :            :   {
    1700                 :          0 :     builder << e.getOperator();
    1701                 :            :   }
    1702         [ -  - ]:          0 :   for (unsigned i = 0; i < e.getNumChildren(); ++i)
    1703                 :            :   {
    1704                 :          0 :     builder << substitute(e[i], substTable, cache);
    1705                 :            :   }
    1706                 :            : 
    1707                 :          0 :   Node result = builder;
    1708                 :            :   // it = substTable.find(result);
    1709                 :            :   // if (it != iend) {
    1710                 :            :   //   result = substitute(it->second, substTable, cache);
    1711                 :            :   // }
    1712                 :          0 :   cache[e] = result;
    1713                 :          0 :   return result;
    1714                 :          0 : }
    1715                 :            : 
    1716                 :          0 : Node ITECareSimplifier::simplifyWithCare(TNode e)
    1717                 :            : {
    1718                 :          0 :   TNodeMap substTable;
    1719                 :            : 
    1720                 :            :   /* This extra block is to trigger the destructors for cs and cs2
    1721                 :            :    * before starting garbage collection.
    1722                 :            :    */
    1723                 :            :   {
    1724                 :          0 :     CareMap queue;
    1725                 :          0 :     CareMap::iterator it;
    1726                 :          0 :     ITECareSimplifier::CareSetPtr cs = getNewSet();
    1727                 :          0 :     ITECareSimplifier::CareSetPtr cs2;
    1728                 :          0 :     queue[e] = cs;
    1729                 :            : 
    1730                 :          0 :     TNode v;
    1731                 :            :     bool done;
    1732                 :            :     unsigned i;
    1733                 :            : 
    1734         [ -  - ]:          0 :     while (!queue.empty())
    1735                 :            :     {
    1736                 :          0 :       it = queue.end();
    1737                 :          0 :       --it;
    1738                 :          0 :       v = it->first;
    1739                 :          0 :       cs = it->second;
    1740                 :          0 :       set<Node>& css = cs.getCareSet();
    1741                 :          0 :       queue.erase(v);
    1742                 :            : 
    1743                 :          0 :       done = false;
    1744                 :          0 :       set<Node>::iterator iCare, iCareEnd = css.end();
    1745                 :            : 
    1746                 :          0 :       switch (v.getKind())
    1747                 :            :       {
    1748                 :          0 :         case Kind::ITE:
    1749                 :            :         {
    1750                 :          0 :           iCare = css.find(v[0]);
    1751         [ -  - ]:          0 :           if (iCare != iCareEnd)
    1752                 :            :           {
    1753                 :          0 :             Assert(substTable.find(v) == substTable.end());
    1754                 :          0 :             substTable[v] = v[1];
    1755                 :          0 :             updateQueue(queue, v[1], cs);
    1756                 :          0 :             done = true;
    1757                 :          0 :             break;
    1758                 :            :           }
    1759                 :            :           else
    1760                 :            :           {
    1761                 :          0 :             iCare = css.find(v[0].negate());
    1762         [ -  - ]:          0 :             if (iCare != iCareEnd)
    1763                 :            :             {
    1764                 :          0 :               Assert(substTable.find(v) == substTable.end());
    1765                 :          0 :               substTable[v] = v[2];
    1766                 :          0 :               updateQueue(queue, v[2], cs);
    1767                 :          0 :               done = true;
    1768                 :          0 :               break;
    1769                 :            :             }
    1770                 :            :           }
    1771                 :          0 :           updateQueue(queue, v[0], cs);
    1772                 :          0 :           cs2 = getNewSet();
    1773                 :          0 :           cs2.getCareSet() = css;
    1774                 :          0 :           cs2.getCareSet().insert(v[0]);
    1775                 :          0 :           updateQueue(queue, v[1], cs2);
    1776                 :          0 :           cs2 = getNewSet();
    1777                 :          0 :           cs2.getCareSet() = css;
    1778                 :          0 :           cs2.getCareSet().insert(v[0].negate());
    1779                 :          0 :           updateQueue(queue, v[2], cs2);
    1780                 :          0 :           done = true;
    1781                 :          0 :           break;
    1782                 :            :         }
    1783                 :          0 :         case Kind::AND:
    1784                 :            :         {
    1785         [ -  - ]:          0 :           for (i = 0; i < v.getNumChildren(); ++i)
    1786                 :            :           {
    1787                 :          0 :             iCare = css.find(v[i].negate());
    1788         [ -  - ]:          0 :             if (iCare != iCareEnd)
    1789                 :            :             {
    1790                 :          0 :               Assert(substTable.find(v) == substTable.end());
    1791                 :          0 :               substTable[v] = d_false;
    1792                 :          0 :               done = true;
    1793                 :          0 :               break;
    1794                 :            :             }
    1795                 :            :           }
    1796         [ -  - ]:          0 :           if (done) break;
    1797                 :            : 
    1798                 :          0 :           Assert(v.getNumChildren() > 1);
    1799                 :          0 :           updateQueue(queue, v[0], cs);
    1800                 :          0 :           cs2 = getNewSet();
    1801                 :          0 :           cs2.getCareSet() = css;
    1802                 :          0 :           cs2.getCareSet().insert(v[0]);
    1803         [ -  - ]:          0 :           for (i = 1; i < v.getNumChildren(); ++i)
    1804                 :            :           {
    1805                 :          0 :             updateQueue(queue, v[i], cs2);
    1806                 :            :           }
    1807                 :          0 :           done = true;
    1808                 :          0 :           break;
    1809                 :            :         }
    1810                 :          0 :         case Kind::OR:
    1811                 :            :         {
    1812         [ -  - ]:          0 :           for (i = 0; i < v.getNumChildren(); ++i)
    1813                 :            :           {
    1814                 :          0 :             iCare = css.find(v[i]);
    1815         [ -  - ]:          0 :             if (iCare != iCareEnd)
    1816                 :            :             {
    1817                 :          0 :               Assert(substTable.find(v) == substTable.end());
    1818                 :          0 :               substTable[v] = d_true;
    1819                 :          0 :               done = true;
    1820                 :          0 :               break;
    1821                 :            :             }
    1822                 :            :           }
    1823         [ -  - ]:          0 :           if (done) break;
    1824                 :            : 
    1825                 :          0 :           Assert(v.getNumChildren() > 1);
    1826                 :          0 :           updateQueue(queue, v[0], cs);
    1827                 :          0 :           cs2 = getNewSet();
    1828                 :          0 :           cs2.getCareSet() = css;
    1829                 :          0 :           cs2.getCareSet().insert(v[0].negate());
    1830         [ -  - ]:          0 :           for (i = 1; i < v.getNumChildren(); ++i)
    1831                 :            :           {
    1832                 :          0 :             updateQueue(queue, v[i], cs2);
    1833                 :            :           }
    1834                 :          0 :           done = true;
    1835                 :          0 :           break;
    1836                 :            :         }
    1837                 :          0 :         default: break;
    1838                 :            :       }
    1839                 :            : 
    1840         [ -  - ]:          0 :       if (done)
    1841                 :            :       {
    1842                 :          0 :         continue;
    1843                 :            :       }
    1844                 :            : 
    1845         [ -  - ]:          0 :       for (i = 0; i < v.getNumChildren(); ++i)
    1846                 :            :       {
    1847                 :          0 :         updateQueue(queue, v[i], cs);
    1848                 :            :       }
    1849                 :            :     }
    1850                 :          0 :   }
    1851                 :            :   /* Perform garbage collection. */
    1852         [ -  - ]:          0 :   while (!d_usedSets.empty())
    1853                 :            :   {
    1854                 :          0 :     CareSetPtrVal* used = d_usedSets.back();
    1855                 :          0 :     d_usedSets.pop_back();
    1856                 :          0 :     Assert(used->safeToGarbageCollect());
    1857         [ -  - ]:          0 :     delete used;
    1858                 :          0 :     Assert(d_careSetsOutstanding > 0);
    1859                 :          0 :     d_careSetsOutstanding--;
    1860                 :            :   }
    1861                 :            : 
    1862                 :          0 :   TNodeMap cache;
    1863                 :          0 :   return substitute(e, substTable, cache);
    1864                 :          0 : }
    1865                 :            : 
    1866                 :          0 : ITECareSimplifier::CareSetPtr ITECareSimplifier::CareSetPtr::mkNew(
    1867                 :            :     ITECareSimplifier& simp)
    1868                 :            : {
    1869                 :          0 :   CareSetPtrVal* val = new CareSetPtrVal(simp);
    1870                 :          0 :   return CareSetPtr(val);
    1871                 :            : }
    1872                 :            : 
    1873                 :            : }  // namespace util
    1874                 :            : }  // namespace preprocessing
    1875                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14