1 /********************* */
2 /*! \file ite_utilities.cpp
4 ** Top contributors (to current version):
5 ** Tim King, Aina Niemetz, Clark Barrett
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8 ** in the top-level source directory and their institutional affiliations.
9 ** All rights reserved. See the file COPYING in the top-level source
10 ** directory for licensing information.\endverbatim
12 ** \brief Simplifications for ITE expressions
14 ** This module implements preprocessing phases designed to simplify ITE
15 ** expressions. Based on:
16 ** Kim, Somenzi, Jin. Efficient Term-ITE Conversion for SMT. FMCAD 2009.
17 ** Burch, Jerry. Techniques for Verifying Superscalar Microprocessors. DAC
20 #include "preprocessing/util/ite_utilities.h"
24 #include "preprocessing/assertion_pipeline.h"
25 #include "preprocessing/passes/rewrite.h"
26 #include "smt/smt_statistics_registry.h"
27 #include "theory/rewriter.h"
28 #include "theory/theory.h"
32 namespace preprocessing
{
37 inline static bool isTermITE(TNode e
)
39 return (e
.getKind() == kind::ITE
&& !e
.getType().isBoolean());
42 inline static bool triviallyContainsNoTermITEs(TNode e
)
44 return e
.isConst() || e
.isVar();
47 static bool isTheoryAtom(TNode a
)
53 case DISTINCT
: return !(a
[0].getType().isBoolean());
56 case APPLY_UF
: return a
.getType().isBoolean();
57 case CARDINALITY_CONSTRAINT
:
72 case BITVECTOR_SGE
: return true;
73 default: return false;
77 struct CTIVStackElement
81 CTIVStackElement() : curr(), pos(0) {}
82 CTIVStackElement(TNode c
) : curr(c
), pos(0) {}
83 }; /* CTIVStackElement */
87 ITEUtilities::ITEUtilities()
88 : d_containsVisitor(new ContainsTermITEVisitor()),
93 Assert(d_containsVisitor
!= NULL
);
96 ITEUtilities::~ITEUtilities()
98 if (d_simplifier
!= NULL
)
102 if (d_compressor
!= NULL
)
106 if (d_careSimp
!= NULL
)
112 Node
ITEUtilities::simpITE(TNode assertion
)
114 if (d_simplifier
== NULL
)
116 d_simplifier
= new ITESimplifier(d_containsVisitor
.get());
118 return d_simplifier
->simpITE(assertion
);
121 bool ITEUtilities::simpIteDidALotOfWorkHeuristic() const
123 if (d_simplifier
== NULL
)
129 return d_simplifier
->doneALotOfWorkHeuristic();
133 /* returns false if an assertion is discovered to be equal to false. */
134 bool ITEUtilities::compress(AssertionPipeline
* assertionsToPreprocess
)
136 if (d_compressor
== NULL
)
138 d_compressor
= new ITECompressor(d_containsVisitor
.get());
140 return d_compressor
->compress(assertionsToPreprocess
);
143 Node
ITEUtilities::simplifyWithCare(TNode e
)
145 if (d_careSimp
== NULL
)
147 d_careSimp
= new ITECareSimplifier();
149 return d_careSimp
->simplifyWithCare(e
);
152 void ITEUtilities::clear()
154 if (d_simplifier
!= NULL
)
156 d_simplifier
->clearSimpITECaches();
158 if (d_compressor
!= NULL
)
160 d_compressor
->garbageCollect();
162 if (d_careSimp
!= NULL
)
166 d_containsVisitor
->garbageCollect();
169 /********************* */
170 /* ContainsTermITEVisitor
172 ContainsTermITEVisitor::ContainsTermITEVisitor() : d_cache() {}
173 ContainsTermITEVisitor::~ContainsTermITEVisitor() {}
174 bool ContainsTermITEVisitor::containsTermITE(TNode e
)
176 /* throughout execution skip through NOT nodes. */
177 e
= (e
.getKind() == kind::NOT
) ? e
[0] : e
;
178 if (ite::triviallyContainsNoTermITEs(e
))
183 NodeBoolMap::const_iterator end
= d_cache
.end();
184 NodeBoolMap::const_iterator tmp_it
= d_cache
.find(e
);
187 return (*tmp_it
).second
;
190 bool foundTermIte
= false;
191 std::vector
<ite::CTIVStackElement
> stack
;
192 stack
.push_back(ite::CTIVStackElement(e
));
193 while (!foundTermIte
&& !stack
.empty())
195 ite::CTIVStackElement
& top
= stack
.back();
196 TNode curr
= top
.curr
;
197 if (top
.pos
>= curr
.getNumChildren())
199 // all of the children have been visited
200 // no term ites were found
201 d_cache
[curr
] = false;
206 // this is someone's child
207 TNode child
= curr
[top
.pos
];
208 child
= (child
.getKind() == kind::NOT
) ? child
[0] : child
;
210 if (ite::triviallyContainsNoTermITEs(child
))
216 tmp_it
= d_cache
.find(child
);
219 foundTermIte
= (*tmp_it
).second
;
223 stack
.push_back(ite::CTIVStackElement(child
));
224 foundTermIte
= ite::isTermITE(child
);
231 while (!stack
.empty())
233 TNode curr
= stack
.back().curr
;
235 d_cache
[curr
] = true;
240 void ContainsTermITEVisitor::garbageCollect() { d_cache
.clear(); }
242 /********************* */
243 /* IncomingArcCounter
245 IncomingArcCounter::IncomingArcCounter(bool skipVars
, bool skipConstants
)
246 : d_reachCount(), d_skipVariables(skipVars
), d_skipConstants(skipConstants
)
249 IncomingArcCounter::~IncomingArcCounter() {}
251 void IncomingArcCounter::computeReachability(
252 const std::vector
<Node
>& assertions
)
254 std::vector
<TNode
> tovisit(assertions
.begin(), assertions
.end());
256 while (!tovisit
.empty())
258 TNode back
= tovisit
.back();
262 switch (back
.getMetaKind())
264 case kind::metakind::CONSTANT
: skip
= d_skipConstants
; break;
265 case kind::metakind::VARIABLE
: skip
= d_skipVariables
; break;
273 if (d_reachCount
.find(back
) != d_reachCount
.end())
275 d_reachCount
[back
] = 1 + d_reachCount
[back
];
279 d_reachCount
[back
] = 1;
280 for (TNode::iterator cit
= back
.begin(), end
= back
.end(); cit
!= end
;
283 tovisit
.push_back(*cit
);
289 void IncomingArcCounter::clear() { d_reachCount
.clear(); }
291 /********************* */
294 ITECompressor::ITECompressor(ContainsTermITEVisitor
* contains
)
295 : d_contains(contains
), d_assertions(NULL
), d_incoming(true, true)
297 Assert(d_contains
!= NULL
);
299 d_true
= NodeManager::currentNM()->mkConst
<bool>(true);
300 d_false
= NodeManager::currentNM()->mkConst
<bool>(false);
303 ITECompressor::~ITECompressor() { reset(); }
305 void ITECompressor::reset()
308 d_compressed
.clear();
311 void ITECompressor::garbageCollect() { reset(); }
313 ITECompressor::Statistics::Statistics()
314 : d_compressCalls("ite-simp::compressCalls", 0),
315 d_skolemsAdded("ite-simp::skolems", 0)
317 smtStatisticsRegistry()->registerStat(&d_compressCalls
);
318 smtStatisticsRegistry()->registerStat(&d_skolemsAdded
);
320 ITECompressor::Statistics::~Statistics()
322 smtStatisticsRegistry()->unregisterStat(&d_compressCalls
);
323 smtStatisticsRegistry()->unregisterStat(&d_skolemsAdded
);
326 Node
ITECompressor::push_back_boolean(Node original
, Node compressed
)
328 Node rewritten
= theory::Rewriter::rewrite(compressed
);
329 // There is a bug if the rewritter takes a pure boolean expression
330 // and changes its theory
331 if (rewritten
.isConst())
333 d_compressed
[compressed
] = rewritten
;
334 d_compressed
[original
] = rewritten
;
335 d_compressed
[rewritten
] = rewritten
;
338 else if (d_compressed
.find(rewritten
) != d_compressed
.end())
340 Node res
= d_compressed
[rewritten
];
341 d_compressed
[original
] = res
;
342 d_compressed
[compressed
] = res
;
345 else if (rewritten
.isVar()
346 || (rewritten
.getKind() == kind::NOT
&& rewritten
[0].isVar()))
348 d_compressed
[original
] = rewritten
;
349 d_compressed
[compressed
] = rewritten
;
350 d_compressed
[rewritten
] = rewritten
;
355 NodeManager
* nm
= NodeManager::currentNM();
356 Node skolem
= nm
->mkSkolem("compress", nm
->booleanType());
357 d_compressed
[rewritten
] = skolem
;
358 d_compressed
[original
] = skolem
;
359 d_compressed
[compressed
] = skolem
;
361 Node iff
= skolem
.eqNode(rewritten
);
362 d_assertions
->push_back(iff
);
363 ++(d_statistics
.d_skolemsAdded
);
368 bool ITECompressor::multipleParents(TNode c
)
370 return d_incoming
.lookupIncoming(c
) >= 2;
373 Node
ITECompressor::compressBooleanITEs(Node toCompress
)
375 Assert(toCompress
.getKind() == kind::ITE
);
376 Assert(toCompress
.getType().isBoolean());
378 if (!(toCompress
[1] == d_false
|| toCompress
[2] == d_false
))
380 Node cmpCnd
= compressBoolean(toCompress
[0]);
381 if (cmpCnd
.isConst())
383 Node branch
= (cmpCnd
== d_true
) ? toCompress
[1] : toCompress
[2];
384 Node res
= compressBoolean(branch
);
385 d_compressed
[toCompress
] = res
;
390 Node cmpThen
= compressBoolean(toCompress
[1]);
391 Node cmpElse
= compressBoolean(toCompress
[2]);
392 Node newIte
= cmpCnd
.iteNode(cmpThen
, cmpElse
);
393 if (multipleParents(toCompress
))
395 return push_back_boolean(toCompress
, newIte
);
404 NodeBuilder
<> nb(kind::AND
);
405 Node curr
= toCompress
;
406 while (curr
.getKind() == kind::ITE
407 && (curr
[1] == d_false
|| curr
[2] == d_false
)
408 && (!multipleParents(curr
) || curr
== toCompress
))
410 bool negateCnd
= (curr
[1] == d_false
);
411 Node compressCnd
= compressBoolean(curr
[0]);
412 if (compressCnd
.isConst())
414 if (compressCnd
.getConst
<bool>() == negateCnd
)
416 return push_back_boolean(toCompress
, d_false
);
420 // equivalent to true don't push back
425 Node pb
= negateCnd
? compressCnd
.notNode() : compressCnd
;
428 curr
= negateCnd
? curr
[2] : curr
[1];
430 Assert(toCompress
!= curr
);
432 nb
<< compressBoolean(curr
);
433 Node res
= nb
.getNumChildren() == 1 ? nb
[0] : (Node
)nb
;
434 return push_back_boolean(toCompress
, res
);
437 Node
ITECompressor::compressTerm(Node toCompress
)
439 if (toCompress
.isConst() || toCompress
.isVar())
444 if (d_compressed
.find(toCompress
) != d_compressed
.end())
446 return d_compressed
[toCompress
];
448 if (toCompress
.getKind() == kind::ITE
)
450 Node cmpCnd
= compressBoolean(toCompress
[0]);
451 if (cmpCnd
.isConst())
453 Node branch
= (cmpCnd
== d_true
) ? toCompress
[1] : toCompress
[2];
454 Node res
= compressTerm(branch
);
455 d_compressed
[toCompress
] = res
;
460 Node cmpThen
= compressTerm(toCompress
[1]);
461 Node cmpElse
= compressTerm(toCompress
[2]);
462 Node newIte
= cmpCnd
.iteNode(cmpThen
, cmpElse
);
463 d_compressed
[toCompress
] = newIte
;
468 NodeBuilder
<> nb(toCompress
.getKind());
470 if (toCompress
.getMetaKind() == kind::metakind::PARAMETERIZED
)
472 nb
<< (toCompress
.getOperator());
474 for (Node::iterator it
= toCompress
.begin(), end
= toCompress
.end();
478 nb
<< compressTerm(*it
);
480 Node compressed
= (Node
)nb
;
481 if (multipleParents(toCompress
))
483 d_compressed
[toCompress
] = compressed
;
488 Node
ITECompressor::compressBoolean(Node toCompress
)
490 static int instance
= 0;
492 if (toCompress
.isConst() || toCompress
.isVar())
496 if (d_compressed
.find(toCompress
) != d_compressed
.end())
498 return d_compressed
[toCompress
];
500 else if (toCompress
.getKind() == kind::ITE
)
502 return compressBooleanITEs(toCompress
);
506 bool ta
= ite::isTheoryAtom(toCompress
);
507 NodeBuilder
<> nb(toCompress
.getKind());
508 if (toCompress
.getMetaKind() == kind::metakind::PARAMETERIZED
)
510 nb
<< (toCompress
.getOperator());
512 for (Node::iterator it
= toCompress
.begin(), end
= toCompress
.end();
516 Node pb
= (ta
) ? compressTerm(*it
) : compressBoolean(*it
);
519 Node compressed
= nb
;
520 if (ta
|| multipleParents(toCompress
))
522 return push_back_boolean(toCompress
, compressed
);
531 bool ITECompressor::compress(AssertionPipeline
* assertionsToPreprocess
)
535 d_assertions
= assertionsToPreprocess
;
536 d_incoming
.computeReachability(assertionsToPreprocess
->ref());
538 ++(d_statistics
.d_compressCalls
);
539 Chat() << "Computed reachability" << endl
;
541 bool nofalses
= true;
542 const std::vector
<Node
>& assertions
= assertionsToPreprocess
->ref();
543 size_t original_size
= assertions
.size();
544 Chat() << "compressing " << original_size
<< endl
;
545 for (size_t i
= 0; i
< original_size
&& nofalses
; ++i
)
547 Node assertion
= assertions
[i
];
548 Node compressed
= compressBoolean(assertion
);
549 Node rewritten
= theory::Rewriter::rewrite(compressed
);
551 assertionsToPreprocess
->replace(i
, rewritten
);
552 Assert(!d_contains
->containsTermITE(rewritten
));
554 nofalses
= (rewritten
!= d_false
);
562 TermITEHeightCounter::TermITEHeightCounter() : d_termITEHeight() {}
564 TermITEHeightCounter::~TermITEHeightCounter() {}
566 void TermITEHeightCounter::clear() { d_termITEHeight
.clear(); }
568 size_t TermITEHeightCounter::cache_size() const
570 return d_termITEHeight
.size();
574 struct TITEHStackElement
578 uint32_t maxChildHeight
;
579 TITEHStackElement() : curr(), pos(0), maxChildHeight(0) {}
580 TITEHStackElement(TNode c
) : curr(c
), pos(0), maxChildHeight(0) {}
582 } /* namespace ite */
584 uint32_t TermITEHeightCounter::termITEHeight(TNode e
)
586 if (ite::triviallyContainsNoTermITEs(e
))
591 NodeCountMap::const_iterator end
= d_termITEHeight
.end();
592 NodeCountMap::const_iterator tmp_it
= d_termITEHeight
.find(e
);
595 return (*tmp_it
).second
;
598 uint32_t returnValue
= 0;
599 // This is initially 0 as the very first call this is included in the max,
600 // but this has no effect.
601 std::vector
<ite::TITEHStackElement
> stack
;
602 stack
.push_back(ite::TITEHStackElement(e
));
603 while (!stack
.empty())
605 ite::TITEHStackElement
& top
= stack
.back();
606 top
.maxChildHeight
= std::max(top
.maxChildHeight
, returnValue
);
607 TNode curr
= top
.curr
;
608 if (top
.pos
>= curr
.getNumChildren())
610 // done with the current node
611 returnValue
= top
.maxChildHeight
+ (ite::isTermITE(curr
) ? 1 : 0);
612 d_termITEHeight
[curr
] = returnValue
;
618 if (top
.pos
== 0 && curr
.getKind() == kind::ITE
)
624 // this is someone's child
625 TNode child
= curr
[top
.pos
];
627 if (ite::triviallyContainsNoTermITEs(child
))
633 tmp_it
= d_termITEHeight
.find(child
);
636 returnValue
= (*tmp_it
).second
;
640 stack
.push_back(ite::TITEHStackElement(child
));
648 ITESimplifier::ITESimplifier(ContainsTermITEVisitor
* contains
)
649 : d_containsVisitor(contains
),
652 d_allocatedConstantLeaves(),
653 d_citeEqConstApplications(0),
654 d_constantIteEqualsConstantCache(),
655 d_replaceOverCache(),
656 d_replaceOverTermIteCache(),
657 d_leavesConstCache(),
659 d_simpContextCache(),
662 Assert(d_containsVisitor
!= NULL
);
663 d_true
= NodeManager::currentNM()->mkConst
<bool>(true);
664 d_false
= NodeManager::currentNM()->mkConst
<bool>(false);
667 ITESimplifier::~ITESimplifier()
669 clearSimpITECaches();
670 Assert(d_constantLeaves
.empty());
671 Assert(d_allocatedConstantLeaves
.empty());
674 bool ITESimplifier::leavesAreConst(TNode e
)
676 return leavesAreConst(e
, theory::Theory::theoryOf(e
));
679 void ITESimplifier::clearSimpITECaches()
681 Chat() << "clear ite caches " << endl
;
682 for (size_t i
= 0, N
= d_allocatedConstantLeaves
.size(); i
< N
; ++i
)
684 NodeVec
* curr
= d_allocatedConstantLeaves
[i
];
687 d_citeEqConstApplications
= 0;
688 d_constantLeaves
.clear();
689 d_allocatedConstantLeaves
.clear();
690 d_termITEHeight
.clear();
691 d_constantIteEqualsConstantCache
.clear();
692 d_replaceOverCache
.clear();
693 d_replaceOverTermIteCache
.clear();
694 d_simpITECache
.clear();
696 d_simpConstCache
.clear();
697 d_leavesConstCache
.clear();
698 d_simpContextCache
.clear();
701 bool ITESimplifier::doneALotOfWorkHeuristic() const
703 static const size_t SIZE_BOUND
= 1000;
704 Chat() << "d_citeEqConstApplications size " << d_citeEqConstApplications
706 return (d_citeEqConstApplications
> SIZE_BOUND
);
709 ITESimplifier::Statistics::Statistics()
710 : d_maxNonConstantsFolded("ite-simp::maxNonConstantsFolded", 0),
711 d_unexpected("ite-simp::unexpected", 0),
712 d_unsimplified("ite-simp::unsimplified", 0),
713 d_exactMatchFold("ite-simp::exactMatchFold", 0),
714 d_binaryPredFold("ite-simp::binaryPredFold", 0),
715 d_specialEqualityFolds("ite-simp::specialEqualityFolds", 0),
716 d_simpITEVisits("ite-simp::simpITE.visits", 0),
717 d_inSmaller("ite-simp::inSmaller")
719 smtStatisticsRegistry()->registerStat(&d_maxNonConstantsFolded
);
720 smtStatisticsRegistry()->registerStat(&d_unexpected
);
721 smtStatisticsRegistry()->registerStat(&d_unsimplified
);
722 smtStatisticsRegistry()->registerStat(&d_exactMatchFold
);
723 smtStatisticsRegistry()->registerStat(&d_binaryPredFold
);
724 smtStatisticsRegistry()->registerStat(&d_specialEqualityFolds
);
725 smtStatisticsRegistry()->registerStat(&d_simpITEVisits
);
726 smtStatisticsRegistry()->registerStat(&d_inSmaller
);
729 ITESimplifier::Statistics::~Statistics()
731 smtStatisticsRegistry()->unregisterStat(&d_maxNonConstantsFolded
);
732 smtStatisticsRegistry()->unregisterStat(&d_unexpected
);
733 smtStatisticsRegistry()->unregisterStat(&d_unsimplified
);
734 smtStatisticsRegistry()->unregisterStat(&d_exactMatchFold
);
735 smtStatisticsRegistry()->unregisterStat(&d_binaryPredFold
);
736 smtStatisticsRegistry()->unregisterStat(&d_specialEqualityFolds
);
737 smtStatisticsRegistry()->unregisterStat(&d_simpITEVisits
);
738 smtStatisticsRegistry()->unregisterStat(&d_inSmaller
);
741 bool ITESimplifier::isConstantIte(TNode e
)
747 else if (ite::isTermITE(e
))
749 NodeVec
* constants
= computeConstantLeaves(e
);
750 return constants
!= NULL
;
758 ITESimplifier::NodeVec
* ITESimplifier::computeConstantLeaves(TNode ite
)
760 Assert(ite::isTermITE(ite
));
761 ConstantLeavesMap::const_iterator it
= d_constantLeaves
.find(ite
);
762 ConstantLeavesMap::const_iterator end
= d_constantLeaves
.end();
767 TNode thenB
= ite
[1];
768 TNode elseB
= ite
[2];
770 // special case 2 constant children
771 if (thenB
.isConst() && elseB
.isConst())
773 NodeVec
* pair
= new NodeVec(2);
774 d_allocatedConstantLeaves
.push_back(pair
);
776 (*pair
)[0] = std::min(thenB
, elseB
);
777 (*pair
)[1] = std::max(thenB
, elseB
);
778 d_constantLeaves
[ite
] = pair
;
781 // At least 1 is an ITE
782 if (!(thenB
.isConst() || thenB
.getKind() == kind::ITE
)
783 || !(elseB
.isConst() || elseB
.getKind() == kind::ITE
))
785 // Cannot be a termITE tree
786 d_constantLeaves
[ite
] = NULL
;
790 // At least 1 is not a constant
791 TNode definitelyITE
= thenB
.isConst() ? elseB
: thenB
;
792 TNode maybeITE
= thenB
.isConst() ? thenB
: elseB
;
794 NodeVec
* defChildren
= computeConstantLeaves(definitelyITE
);
795 if (defChildren
== NULL
)
797 d_constantLeaves
[ite
] = NULL
;
802 NodeVec
* maybeChildren
= NULL
;
803 if (maybeITE
.getKind() == kind::ITE
)
805 maybeChildren
= computeConstantLeaves(maybeITE
);
809 scratch
.push_back(maybeITE
);
810 maybeChildren
= &scratch
;
812 if (maybeChildren
== NULL
)
814 d_constantLeaves
[ite
] = NULL
;
818 NodeVec
* both
= new NodeVec(defChildren
->size() + maybeChildren
->size());
819 d_allocatedConstantLeaves
.push_back(both
);
820 NodeVec::iterator newEnd
;
821 newEnd
= std::set_union(defChildren
->begin(),
823 maybeChildren
->begin(),
824 maybeChildren
->end(),
826 both
->resize(newEnd
- both
->begin());
827 d_constantLeaves
[ite
] = both
;
831 // This is uncached! Better for protoyping or getting limited size examples
832 struct IteTreeSearchData
836 set
<Node
> nonConstants
;
842 : maxConstants(-1), maxNonconstants(-1), maxDepth(-1), failure(false)
846 void iteTreeSearch(Node e
, int depth
, IteTreeSearchData
& search
)
848 if (search
.maxDepth
>= 0 && depth
> search
.maxDepth
)
850 search
.failure
= true;
856 if (search
.visited
.find(e
) != search
.visited
.end())
862 search
.visited
.insert(e
);
867 search
.constants
.insert(e
);
868 if (search
.maxConstants
>= 0
869 && search
.constants
.size() > (unsigned)search
.maxConstants
)
871 search
.failure
= true;
874 else if (e
.getKind() == kind::ITE
)
876 iteTreeSearch(e
[1], depth
+ 1, search
);
877 iteTreeSearch(e
[2], depth
+ 1, search
);
881 search
.nonConstants
.insert(e
);
882 if (search
.maxNonconstants
>= 0
883 && search
.nonConstants
.size() > (unsigned)search
.maxNonconstants
)
885 search
.failure
= true;
890 Node
ITESimplifier::replaceOver(Node n
, Node replaceWith
, Node simpVar
)
896 else if (n
.getNumChildren() == 0)
900 Assert(n
.getNumChildren() > 0);
903 pair
<Node
, Node
> p
= make_pair(n
, replaceWith
);
904 if (d_replaceOverCache
.find(p
) != d_replaceOverCache
.end())
906 return d_replaceOverCache
[p
];
909 NodeBuilder
<> builder(n
.getKind());
910 if (n
.getMetaKind() == kind::metakind::PARAMETERIZED
)
912 builder
<< n
.getOperator();
915 for (; i
< n
.getNumChildren(); ++i
)
917 Node newChild
= replaceOver(n
[i
], replaceWith
, simpVar
);
920 // Mark the substitution and continue
921 Node result
= builder
;
922 d_replaceOverCache
[p
] = result
;
926 Node
ITESimplifier::replaceOverTermIte(Node e
, Node simpAtom
, Node simpVar
)
928 if (e
.getKind() == kind::ITE
)
930 pair
<Node
, Node
> p
= make_pair(e
, simpAtom
);
931 if (d_replaceOverTermIteCache
.find(p
) != d_replaceOverTermIteCache
.end())
933 return d_replaceOverTermIteCache
[p
];
935 Assert(!e
.getType().isBoolean());
937 Node newThen
= replaceOverTermIte(e
[1], simpAtom
, simpVar
);
938 Node newElse
= replaceOverTermIte(e
[2], simpAtom
, simpVar
);
939 Node newIte
= cnd
.iteNode(newThen
, newElse
);
940 d_replaceOverTermIteCache
[p
] = newIte
;
945 return replaceOver(simpAtom
, e
, simpVar
);
949 Node
ITESimplifier::attemptLiftEquality(TNode atom
)
951 if (atom
.getKind() == kind::EQUAL
)
953 TNode left
= atom
[0];
954 TNode right
= atom
[1];
955 if ((left
.getKind() == kind::ITE
|| right
.getKind() == kind::ITE
)
956 && !(left
.getKind() == kind::ITE
&& right
.getKind() == kind::ITE
))
958 // exactly 1 is an ite
959 TNode ite
= left
.getKind() == kind::ITE
? left
: right
;
960 TNode notIte
= left
.getKind() == kind::ITE
? right
: left
;
962 if (notIte
== ite
[1])
964 ++(d_statistics
.d_exactMatchFold
);
965 return ite
[0].iteNode(d_true
, notIte
.eqNode(ite
[2]));
967 else if (notIte
== ite
[2])
969 ++(d_statistics
.d_exactMatchFold
);
970 return ite
[0].iteNode(notIte
.eqNode(ite
[1]), d_true
);
972 if (notIte
.isConst() && (ite
[1].isConst() || ite
[2].isConst()))
974 ++(d_statistics
.d_exactMatchFold
);
975 return ite
[0].iteNode(notIte
.eqNode(ite
[1]), notIte
.eqNode(ite
[2]));
980 // try a similar more relaxed version for non-equality operators
981 if (atom
.getMetaKind() == kind::metakind::OPERATOR
982 && atom
.getNumChildren() == 2 && !atom
[1].getType().isBoolean())
984 TNode left
= atom
[0];
985 TNode right
= atom
[1];
986 if ((left
.getKind() == kind::ITE
|| right
.getKind() == kind::ITE
)
987 && !(left
.getKind() == kind::ITE
&& right
.getKind() == kind::ITE
))
989 // exactly 1 is an ite
990 bool leftIsIte
= left
.getKind() == kind::ITE
;
991 Node ite
= leftIsIte
? left
: right
;
992 Node notIte
= leftIsIte
? right
: left
;
994 if (notIte
.isConst())
996 IteTreeSearchData search
;
997 search
.maxNonconstants
= 2;
998 iteTreeSearch(ite
, 0, search
);
1001 d_statistics
.d_maxNonConstantsFolded
.maxAssign(
1002 search
.nonConstants
.size());
1003 Debug("ite::simpite") << "used " << search
.nonConstants
.size()
1004 << " nonconstants" << endl
;
1005 NodeManager
* nm
= NodeManager::currentNM();
1006 Node simpVar
= getSimpVar(notIte
.getType());
1007 TNode newLeft
= leftIsIte
? simpVar
: notIte
;
1008 TNode newRight
= leftIsIte
? notIte
: simpVar
;
1009 Node newAtom
= nm
->mkNode(atom
.getKind(), newLeft
, newRight
);
1011 ++(d_statistics
.d_binaryPredFold
);
1012 return replaceOverTermIte(ite
, newAtom
, simpVar
);
1018 // TODO "This is way too tailored. Must generalize!"
1019 if (atom
.getKind() == kind::EQUAL
&& atom
.getNumChildren() == 2
1020 && ite::isTermITE(atom
[0]) && atom
[1].getKind() == kind::MULT
1021 && atom
[1].getNumChildren() == 2 && atom
[1][0].isConst()
1022 && atom
[1][0].getConst
<Rational
>().isNegativeOne()
1023 && ite::isTermITE(atom
[1][1])
1024 && d_termITEHeight
.termITEHeight(atom
[0]) == 1
1025 && d_termITEHeight
.termITEHeight(atom
[1][1]) == 1
1026 && (atom
[0][1].isConst() || atom
[0][2].isConst())
1027 && (atom
[1][1][1].isConst() || atom
[1][1][2].isConst()))
1029 // expand all 4 cases
1031 Node negOne
= atom
[1][0];
1033 Node lite
= atom
[0];
1038 NodeManager
* nm
= NodeManager::currentNM();
1039 Node negRite
= atom
[1][1];
1040 Node rC
= negRite
[0];
1041 Node rT
= nm
->mkNode(kind::MULT
, negOne
, negRite
[1]);
1042 Node rE
= nm
->mkNode(kind::MULT
, negOne
, negRite
[2]);
1044 // (ite lC lT lE) = (ite rC rT rE)
1045 // (ite lc (= lT (ite rC rT rE) (= lE (ite rC rT rE))))
1046 // (ite lc (ite rC (= lT rT) (= lT rE))
1047 // (ite rC (= lE rT) (= lE rE)))
1049 Node eqTT
= lT
.eqNode(rT
);
1050 Node eqTE
= lT
.eqNode(rE
);
1051 Node eqET
= lE
.eqNode(rT
);
1052 Node eqEE
= lE
.eqNode(rE
);
1053 Node thenLC
= rC
.iteNode(eqTT
, eqTE
);
1054 Node elseLC
= rC
.iteNode(eqET
, eqEE
);
1055 Node newIte
= lC
.iteNode(thenLC
, elseLC
);
1057 ++(d_statistics
.d_specialEqualityFolds
);
1060 return Node::null();
1063 // Interesting classes of atoms:
1064 // 2. Contains constants and 1 constant term ite
1065 // 3. Contains 2 constant term ites
1066 Node
ITESimplifier::transformAtom(TNode atom
)
1068 if (!d_containsVisitor
->containsTermITE(atom
))
1070 if (atom
.getKind() == kind::EQUAL
&& atom
[0].isConst() && atom
[1].isConst())
1072 // constant equality
1073 return NodeManager::currentNM()->mkConst
<bool>(atom
[0] == atom
[1]);
1075 return Node::null();
1079 Node acr
= attemptConstantRemoval(atom
);
1084 // Node ale = attemptLiftEquality(atom);
1085 // if(!ale.isNull()){
1088 return Node::null();
1092 static unsigned numBranches
= 0;
1093 static unsigned numFalseBranches
= 0;
1094 static unsigned itesMade
= 0;
1096 Node
ITESimplifier::constantIteEqualsConstant(TNode cite
, TNode constant
)
1098 static int instance
= 0;
1100 Debug("ite::constantIteEqualsConstant")
1101 << instance
<< "constantIteEqualsConstant(" << cite
<< ", " << constant
1105 Node res
= (cite
== constant
) ? d_true
: d_false
;
1106 Debug("ite::constantIteEqualsConstant") << instance
<< "->" << res
<< endl
;
1109 std::pair
<Node
, Node
> pair
= make_pair(cite
, constant
);
1111 NodePairMap::const_iterator eq_pos
=
1112 d_constantIteEqualsConstantCache
.find(pair
);
1113 if (eq_pos
!= d_constantIteEqualsConstantCache
.end())
1115 Debug("ite::constantIteEqualsConstant")
1116 << instance
<< "->" << (*eq_pos
).second
<< endl
;
1117 return (*eq_pos
).second
;
1120 ++d_citeEqConstApplications
;
1122 NodeVec
* leaves
= computeConstantLeaves(cite
);
1123 Assert(leaves
!= NULL
);
1124 if (std::binary_search(leaves
->begin(), leaves
->end(), constant
))
1126 if (leaves
->size() == 1)
1128 // probably unreachable
1129 d_constantIteEqualsConstantCache
[pair
] = d_true
;
1130 Debug("ite::constantIteEqualsConstant")
1131 << instance
<< "->" << d_true
<< endl
;
1136 Assert(cite
.getKind() == kind::ITE
);
1137 TNode cnd
= cite
[0];
1140 Node tEqs
= constantIteEqualsConstant(tB
, constant
);
1141 Node fEqs
= constantIteEqualsConstant(fB
, constant
);
1142 Node boolIte
= cnd
.iteNode(tEqs
, fEqs
);
1143 if (!(tEqs
.isConst() || fEqs
.isConst()))
1147 if (!(tEqs
== d_false
|| fEqs
== d_false
))
1152 d_constantIteEqualsConstantCache
[pair
] = boolIte
;
1153 // Debug("ite::constantIteEqualsConstant") << instance << "->" << boolIte
1160 d_constantIteEqualsConstantCache
[pair
] = d_false
;
1161 Debug("ite::constantIteEqualsConstant")
1162 << instance
<< "->" << d_false
<< endl
;
1167 Node
ITESimplifier::intersectConstantIte(TNode lcite
, TNode rcite
)
1169 // intersect the constant ite trees lcite and rcite
1171 if (lcite
.isConst() || rcite
.isConst())
1173 bool lIsConst
= lcite
.isConst();
1174 TNode constant
= lIsConst
? lcite
: rcite
;
1175 TNode cite
= lIsConst
? rcite
: lcite
;
1177 (d_statistics
.d_inSmaller
) << 1;
1178 unsigned preItesMade
= itesMade
;
1179 unsigned preNumBranches
= numBranches
;
1180 unsigned preNumFalseBranches
= numFalseBranches
;
1181 Node bterm
= constantIteEqualsConstant(cite
, constant
);
1182 Debug("intersectConstantIte") << (numBranches
- preNumBranches
) << " "
1183 << (numFalseBranches
- preNumFalseBranches
)
1184 << " " << (itesMade
- preItesMade
) << endl
;
1187 Assert(lcite
.getKind() == kind::ITE
);
1188 Assert(rcite
.getKind() == kind::ITE
);
1190 NodeVec
* leftValues
= computeConstantLeaves(lcite
);
1191 NodeVec
* rightValues
= computeConstantLeaves(rcite
);
1193 uint32_t smaller
= std::min(leftValues
->size(), rightValues
->size());
1195 (d_statistics
.d_inSmaller
) << smaller
;
1196 NodeVec
intersection(smaller
, Node::null());
1197 NodeVec::iterator newEnd
;
1198 newEnd
= std::set_intersection(leftValues
->begin(),
1200 rightValues
->begin(),
1202 intersection
.begin());
1203 intersection
.resize(newEnd
- intersection
.begin());
1204 if (intersection
.empty())
1210 NodeBuilder
<> nb(kind::OR
);
1211 NodeVec::const_iterator it
= intersection
.begin(), end
= intersection
.end();
1212 for (; it
!= end
; ++it
)
1215 Node lefteq
= constantIteEqualsConstant(lcite
, inBoth
);
1216 Node righteq
= constantIteEqualsConstant(rcite
, inBoth
);
1217 Node bothHold
= lefteq
.andNode(righteq
);
1220 Node result
= (nb
.getNumChildren() > 1) ? (Node
)nb
: nb
[0];
1225 Node
ITESimplifier::attemptEagerRemoval(TNode atom
)
1227 if (atom
.getKind() == kind::EQUAL
)
1229 TNode left
= atom
[0];
1230 TNode right
= atom
[1];
1231 if ((left
.isConst() && right
.getKind() == kind::ITE
&& isConstantIte(right
))
1232 || (right
.isConst() && left
.getKind() == kind::ITE
1233 && isConstantIte(left
)))
1235 TNode constant
= left
.isConst() ? left
: right
;
1236 TNode cite
= left
.isConst() ? right
: left
;
1238 std::pair
<Node
, Node
> pair
= make_pair(cite
, constant
);
1239 NodePairMap::const_iterator eq_pos
=
1240 d_constantIteEqualsConstantCache
.find(pair
);
1241 if (eq_pos
!= d_constantIteEqualsConstantCache
.end())
1243 Node ret
= (*eq_pos
).second
;
1250 return Node::null();
1254 NodeVec
* leaves
= computeConstantLeaves(cite
);
1255 Assert(leaves
!= NULL
);
1256 if (!std::binary_search(leaves
->begin(), leaves
->end(), constant
))
1258 d_constantIteEqualsConstantCache
[pair
] = d_false
;
1263 return Node::null();
1266 Node
ITESimplifier::attemptConstantRemoval(TNode atom
)
1268 if (atom
.getKind() == kind::EQUAL
)
1270 TNode left
= atom
[0];
1271 TNode right
= atom
[1];
1272 if (isConstantIte(left
) && isConstantIte(right
))
1274 return intersectConstantIte(left
, right
);
1277 return Node::null();
1280 bool ITESimplifier::leavesAreConst(TNode e
, theory::TheoryId tid
)
1282 Assert((e
.getKind() == kind::ITE
&& !e
.getType().isBoolean())
1283 || theory::Theory::theoryOf(e
) != theory::THEORY_BOOL
);
1289 unordered_map
<Node
, bool, NodeHashFunction
>::iterator it
;
1290 it
= d_leavesConstCache
.find(e
);
1291 if (it
!= d_leavesConstCache
.end())
1293 return (*it
).second
;
1296 if (!containsTermITE(e
) && theory::Theory::isLeafOf(e
, tid
))
1298 d_leavesConstCache
[e
] = false;
1302 Assert(e
.getNumChildren() > 0);
1303 size_t k
= 0, sz
= e
.getNumChildren();
1305 if (e
.getKind() == kind::ITE
)
1312 if (!leavesAreConst(e
[k
], tid
))
1314 d_leavesConstCache
[e
] = false;
1318 d_leavesConstCache
[e
] = true;
1322 Node
ITESimplifier::simpConstants(TNode simpContext
,
1326 NodePairMap::iterator it
;
1327 it
= d_simpConstCache
.find(pair
<Node
, Node
>(simpContext
, iteNode
));
1328 if (it
!= d_simpConstCache
.end())
1330 return (*it
).second
;
1333 if (iteNode
.getKind() == kind::ITE
)
1335 NodeBuilder
<> builder(kind::ITE
);
1336 builder
<< iteNode
[0];
1338 for (; i
< iteNode
.getNumChildren(); ++i
)
1340 Node n
= simpConstants(simpContext
, iteNode
[i
], simpVar
);
1347 // Mark the substitution and continue
1348 Node result
= builder
;
1349 result
= theory::Rewriter::rewrite(result
);
1350 d_simpConstCache
[pair
<Node
, Node
>(simpContext
, iteNode
)] = result
;
1354 if (!containsTermITE(iteNode
))
1357 theory::Rewriter::rewrite(simpContext
.substitute(simpVar
, iteNode
));
1358 d_simpConstCache
[pair
<Node
, Node
>(simpContext
, iteNode
)] = n
;
1364 d_simpContextCache
.clear();
1365 Node simpContext2
= createSimpContext(iteNode
, iteNode2
, simpVar2
);
1366 if (!simpContext2
.isNull())
1368 Assert(!iteNode2
.isNull());
1369 simpContext2
= simpContext
.substitute(simpVar
, simpContext2
);
1370 Node n
= simpConstants(simpContext2
, iteNode2
, simpVar2
);
1375 d_simpConstCache
[pair
<Node
, Node
>(simpContext
, iteNode
)] = n
;
1381 Node
ITESimplifier::getSimpVar(TypeNode t
)
1383 std::unordered_map
<TypeNode
, Node
, TypeNode::HashFunction
>::iterator it
;
1384 it
= d_simpVars
.find(t
);
1385 if (it
!= d_simpVars
.end())
1387 return (*it
).second
;
1391 Node var
= NodeManager::currentNM()->mkSkolem(
1392 "iteSimp", t
, "is a variable resulting from ITE simplification");
1393 d_simpVars
[t
] = var
;
1398 Node
ITESimplifier::createSimpContext(TNode c
, Node
& iteNode
, Node
& simpVar
)
1400 NodeMap::iterator it
;
1401 it
= d_simpContextCache
.find(c
);
1402 if (it
!= d_simpContextCache
.end())
1404 return (*it
).second
;
1407 if (!containsTermITE(c
))
1409 d_simpContextCache
[c
] = c
;
1413 if (c
.getKind() == kind::ITE
&& !c
.getType().isBoolean())
1415 // Currently only support one ite node in a simp context
1416 // Return Null if more than one is found
1417 if (!iteNode
.isNull())
1421 simpVar
= getSimpVar(c
.getType());
1422 if (simpVar
.isNull())
1426 d_simpContextCache
[c
] = simpVar
;
1431 NodeBuilder
<> builder(c
.getKind());
1432 if (c
.getMetaKind() == kind::metakind::PARAMETERIZED
)
1434 builder
<< c
.getOperator();
1437 for (; i
< c
.getNumChildren(); ++i
)
1439 Node newChild
= createSimpContext(c
[i
], iteNode
, simpVar
);
1440 if (newChild
.isNull())
1444 builder
<< newChild
;
1446 // Mark the substitution and continue
1447 Node result
= builder
;
1448 d_simpContextCache
[c
] = result
;
1451 typedef std::unordered_set
<Node
, NodeHashFunction
> NodeSet
;
1452 void countReachable_(Node x
, Kind k
, NodeSet
& visited
, uint32_t& reached
)
1454 if (visited
.find(x
) != visited
.end())
1459 if (x
.getKind() == k
)
1463 for (unsigned i
= 0, N
= x
.getNumChildren(); i
< N
; ++i
)
1465 countReachable_(x
[i
], k
, visited
, reached
);
1469 uint32_t countReachable(TNode x
, Kind k
)
1472 uint32_t reached
= 0;
1473 countReachable_(x
, k
, visited
, reached
);
1477 Node
ITESimplifier::simpITEAtom(TNode atom
)
1479 static int CVC4_UNUSED instance
= 0;
1480 Debug("ite::atom") << "still simplifying " << (++instance
) << endl
;
1481 Node attempt
= transformAtom(atom
);
1482 Debug("ite::atom") << " finished " << instance
<< endl
;
1483 if (!attempt
.isNull())
1485 Node rewritten
= theory::Rewriter::rewrite(attempt
);
1486 Debug("ite::print-success")
1488 << "rewriting " << countReachable(rewritten
, kind::ITE
) << " from "
1489 << countReachable(atom
, kind::ITE
) << endl
1490 << "\t rewritten " << rewritten
<< endl
1491 << "\t input " << atom
<< endl
;
1495 if (leavesAreConst(atom
))
1499 d_simpContextCache
.clear();
1500 Node simpContext
= createSimpContext(atom
, iteNode
, simpVar
);
1501 if (!simpContext
.isNull())
1503 if (iteNode
.isNull())
1505 Assert(leavesAreConst(simpContext
) && !containsTermITE(simpContext
));
1506 ++(d_statistics
.d_unexpected
);
1507 Debug("ite::simpite") << instance
<< " "
1508 << "how about?" << atom
<< endl
;
1509 Debug("ite::simpite") << instance
<< " "
1510 << "\t" << simpContext
<< endl
;
1511 return theory::Rewriter::rewrite(simpContext
);
1513 Node n
= simpConstants(simpContext
, iteNode
, simpVar
);
1516 ++(d_statistics
.d_unexpected
);
1517 Debug("ite::simpite") << instance
<< " "
1518 << "here?" << atom
<< endl
;
1519 Debug("ite::simpite") << instance
<< " "
1520 << "\t" << n
<< endl
;
1525 if (Debug
.isOn("ite::simpite"))
1527 if (countReachable(atom
, kind::ITE
) > 0)
1529 Debug("ite::simpite") << instance
<< " "
1530 << "remaining " << atom
<< endl
;
1533 ++(d_statistics
.d_unsimplified
);
1537 struct preprocess_stack_element
1540 bool d_children_added
;
1541 preprocess_stack_element(TNode node
) : d_node(node
), d_children_added(false)
1544 }; /* struct preprocess_stack_element */
1546 Node
ITESimplifier::simpITE(TNode assertion
)
1548 // Do a topological sort of the subexpressions and substitute them
1549 vector
<preprocess_stack_element
> toVisit
;
1550 toVisit
.push_back(assertion
);
1552 static int call
= 0;
1556 while (!toVisit
.empty())
1559 // cout << "call " << call << " : " << iteration << endl;
1560 // The current node we are processing
1561 preprocess_stack_element
& stackHead
= toVisit
.back();
1562 TNode current
= stackHead
.d_node
;
1564 // If node has no ITE's or already in the cache we're done, pop from the
1566 if (current
.getNumChildren() == 0
1567 || (theory::Theory::theoryOf(current
) != theory::THEORY_BOOL
1568 && !containsTermITE(current
)))
1570 d_simpITECache
[current
] = current
;
1571 ++(d_statistics
.d_simpITEVisits
);
1576 NodeMap::iterator find
= d_simpITECache
.find(current
);
1577 if (find
!= d_simpITECache
.end())
1583 // Not yet substituted, so process
1584 if (stackHead
.d_children_added
)
1586 // Children have been processed, so substitute
1587 NodeBuilder
<> builder(current
.getKind());
1588 if (current
.getMetaKind() == kind::metakind::PARAMETERIZED
)
1590 builder
<< current
.getOperator();
1592 for (unsigned i
= 0; i
< current
.getNumChildren(); ++i
)
1594 Assert(d_simpITECache
.find(current
[i
]) != d_simpITECache
.end());
1595 Node child
= current
[i
];
1596 Node childRes
= d_simpITECache
[current
[i
]];
1597 builder
<< childRes
;
1599 // Mark the substitution and continue
1600 Node result
= builder
;
1602 // If this is an atom, we process it
1603 if (theory::Theory::theoryOf(result
) != theory::THEORY_BOOL
1604 && result
.getType().isBoolean())
1606 result
= simpITEAtom(result
);
1609 // if(current != result && result.isConst()){
1610 // static int instance = 0;
1611 // //cout << instance << " " << result << current << endl;
1614 result
= theory::Rewriter::rewrite(result
);
1615 d_simpITECache
[current
] = result
;
1616 ++(d_statistics
.d_simpITEVisits
);
1621 // Mark that we have added the children if any
1622 if (current
.getNumChildren() > 0)
1624 stackHead
.d_children_added
= true;
1625 // We need to add the children
1626 for (TNode::iterator child_it
= current
.begin();
1627 child_it
!= current
.end();
1630 TNode childNode
= *child_it
;
1631 NodeMap::iterator childFind
= d_simpITECache
.find(childNode
);
1632 if (childFind
== d_simpITECache
.end())
1634 toVisit
.push_back(childNode
);
1640 // No children, so we're done
1641 d_simpITECache
[current
] = current
;
1642 ++(d_statistics
.d_simpITEVisits
);
1647 return d_simpITECache
[assertion
];
1650 ITECareSimplifier::ITECareSimplifier() : d_careSetsOutstanding(0), d_usedSets()
1652 d_true
= NodeManager::currentNM()->mkConst
<bool>(true);
1653 d_false
= NodeManager::currentNM()->mkConst
<bool>(false);
1656 ITECareSimplifier::~ITECareSimplifier()
1658 Assert(d_usedSets
.empty());
1659 Assert(d_careSetsOutstanding
== 0);
1662 void ITECareSimplifier::clear()
1664 Assert(d_usedSets
.empty());
1665 Assert(d_careSetsOutstanding
== 0);
1668 ITECareSimplifier::CareSetPtr
ITECareSimplifier::getNewSet()
1670 if (d_usedSets
.empty())
1672 d_careSetsOutstanding
++;
1673 return ITECareSimplifier::CareSetPtr::mkNew(*this);
1677 ITECareSimplifier::CareSetPtr cs
=
1678 ITECareSimplifier::CareSetPtr::recycle(d_usedSets
.back());
1679 cs
.getCareSet().clear();
1680 d_usedSets
.pop_back();
1685 void ITECareSimplifier::updateQueue(CareMap
& queue
,
1687 ITECareSimplifier::CareSetPtr
& careSet
)
1689 CareMap::iterator it
= queue
.find(e
), iend
= queue
.end();
1692 set
<Node
>& cs2
= (*it
).second
.getCareSet();
1693 ITECareSimplifier::CareSetPtr csNew
= getNewSet();
1694 set_intersection(careSet
.getCareSet().begin(),
1695 careSet
.getCareSet().end(),
1698 inserter(csNew
.getCareSet(), csNew
.getCareSet().begin()));
1699 (*it
).second
= csNew
;
1707 Node
ITECareSimplifier::substitute(TNode e
,
1708 TNodeMap
& substTable
,
1711 TNodeMap::iterator it
= cache
.find(e
), iend
= cache
.end();
1718 it
= substTable
.find(e
);
1719 iend
= substTable
.end();
1722 Node result
= substitute(it
->second
, substTable
, cache
);
1727 size_t sz
= e
.getNumChildren();
1734 NodeBuilder
<> builder(e
.getKind());
1735 if (e
.getMetaKind() == kind::metakind::PARAMETERIZED
)
1737 builder
<< e
.getOperator();
1739 for (unsigned i
= 0; i
< e
.getNumChildren(); ++i
)
1741 builder
<< substitute(e
[i
], substTable
, cache
);
1744 Node result
= builder
;
1745 // it = substTable.find(result);
1746 // if (it != iend) {
1747 // result = substitute(it->second, substTable, cache);
1753 Node
ITECareSimplifier::simplifyWithCare(TNode e
)
1755 TNodeMap substTable
;
1757 /* This extra block is to trigger the destructors for cs and cs2
1758 * before starting garbage collection.
1762 CareMap::iterator it
;
1763 ITECareSimplifier::CareSetPtr cs
= getNewSet();
1764 ITECareSimplifier::CareSetPtr cs2
;
1771 while (!queue
.empty())
1777 set
<Node
>& css
= cs
.getCareSet();
1781 set
<Node
>::iterator iCare
, iCareEnd
= css
.end();
1783 switch (v
.getKind())
1787 iCare
= css
.find(v
[0]);
1788 if (iCare
!= iCareEnd
)
1790 Assert(substTable
.find(v
) == substTable
.end());
1791 substTable
[v
] = v
[1];
1792 updateQueue(queue
, v
[1], cs
);
1798 iCare
= css
.find(v
[0].negate());
1799 if (iCare
!= iCareEnd
)
1801 Assert(substTable
.find(v
) == substTable
.end());
1802 substTable
[v
] = v
[2];
1803 updateQueue(queue
, v
[2], cs
);
1808 updateQueue(queue
, v
[0], cs
);
1810 cs2
.getCareSet() = css
;
1811 cs2
.getCareSet().insert(v
[0]);
1812 updateQueue(queue
, v
[1], cs2
);
1814 cs2
.getCareSet() = css
;
1815 cs2
.getCareSet().insert(v
[0].negate());
1816 updateQueue(queue
, v
[2], cs2
);
1822 for (i
= 0; i
< v
.getNumChildren(); ++i
)
1824 iCare
= css
.find(v
[i
].negate());
1825 if (iCare
!= iCareEnd
)
1827 Assert(substTable
.find(v
) == substTable
.end());
1828 substTable
[v
] = d_false
;
1835 Assert(v
.getNumChildren() > 1);
1836 updateQueue(queue
, v
[0], cs
);
1838 cs2
.getCareSet() = css
;
1839 cs2
.getCareSet().insert(v
[0]);
1840 for (i
= 1; i
< v
.getNumChildren(); ++i
)
1842 updateQueue(queue
, v
[i
], cs2
);
1849 for (i
= 0; i
< v
.getNumChildren(); ++i
)
1851 iCare
= css
.find(v
[i
]);
1852 if (iCare
!= iCareEnd
)
1854 Assert(substTable
.find(v
) == substTable
.end());
1855 substTable
[v
] = d_true
;
1862 Assert(v
.getNumChildren() > 1);
1863 updateQueue(queue
, v
[0], cs
);
1865 cs2
.getCareSet() = css
;
1866 cs2
.getCareSet().insert(v
[0].negate());
1867 for (i
= 1; i
< v
.getNumChildren(); ++i
)
1869 updateQueue(queue
, v
[i
], cs2
);
1882 for (i
= 0; i
< v
.getNumChildren(); ++i
)
1884 updateQueue(queue
, v
[i
], cs
);
1888 /* Perform garbage collection. */
1889 while (!d_usedSets
.empty())
1891 CareSetPtrVal
* used
= d_usedSets
.back();
1892 d_usedSets
.pop_back();
1893 Assert(used
->safeToGarbageCollect());
1895 Assert(d_careSetsOutstanding
> 0);
1896 d_careSetsOutstanding
--;
1900 return substitute(e
, substTable
, cache
);
1903 ITECareSimplifier::CareSetPtr
ITECareSimplifier::CareSetPtr::mkNew(
1904 ITECareSimplifier
& simp
)
1906 CareSetPtrVal
* val
= new CareSetPtrVal(simp
);
1907 return CareSetPtr(val
);
1911 } // namespace preprocessing