diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp')
| -rw-r--r-- | contrib/llvm-project/clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp | 333 |
1 files changed, 147 insertions, 186 deletions
diff --git a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp index caa1ed266c5f..037886d09c4f 100644 --- a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp +++ b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp @@ -17,9 +17,10 @@ #include <queue> #include <vector> +#include "clang/Analysis/FlowSensitive/Formula.h" #include "clang/Analysis/FlowSensitive/Solver.h" -#include "clang/Analysis/FlowSensitive/Value.h" #include "clang/Analysis/FlowSensitive/WatchedLiteralsSolver.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/STLExtras.h" @@ -78,7 +79,7 @@ using ClauseID = uint32_t; static constexpr ClauseID NullClause = 0; /// A boolean formula in conjunctive normal form. -struct BooleanFormula { +struct CNFFormula { /// `LargestVar` is equal to the largest positive integer that represents a /// variable in the formula. const Variable LargestVar; @@ -120,12 +121,12 @@ struct BooleanFormula { /// clauses in the formula start from the element at index 1. std::vector<ClauseID> NextWatched; - /// Stores the variable identifier and value location for atomic booleans in - /// the formula. - llvm::DenseMap<Variable, AtomicBoolValue *> Atomics; + /// Stores the variable identifier and Atom for atomic booleans in the + /// formula. + llvm::DenseMap<Variable, Atom> Atomics; - explicit BooleanFormula(Variable LargestVar, - llvm::DenseMap<Variable, AtomicBoolValue *> Atomics) + explicit CNFFormula(Variable LargestVar, + llvm::DenseMap<Variable, Atom> Atomics) : LargestVar(LargestVar), Atomics(std::move(Atomics)) { Clauses.push_back(0); ClauseStarts.push_back(0); @@ -143,8 +144,8 @@ struct BooleanFormula { /// /// All literals in the input that are not `NullLit` must be distinct. void addClause(Literal L1, Literal L2 = NullLit, Literal L3 = NullLit) { - // The literals are guaranteed to be distinct from properties of BoolValue - // and the construction in `buildBooleanFormula`. + // The literals are guaranteed to be distinct from properties of Formula + // and the construction in `buildCNF`. assert(L1 != NullLit && L1 != L2 && L1 != L3 && (L2 != L3 || L2 == NullLit)); @@ -177,98 +178,59 @@ struct BooleanFormula { /// Converts the conjunction of `Vals` into a formula in conjunctive normal /// form where each clause has at least one and at most three literals. -BooleanFormula buildBooleanFormula(const llvm::DenseSet<BoolValue *> &Vals) { +CNFFormula buildCNF(const llvm::ArrayRef<const Formula *> &Vals) { // The general strategy of the algorithm implemented below is to map each // of the sub-values in `Vals` to a unique variable and use these variables in // the resulting CNF expression to avoid exponential blow up. The number of // literals in the resulting formula is guaranteed to be linear in the number - // of sub-values in `Vals`. + // of sub-formulas in `Vals`. - // Map each sub-value in `Vals` to a unique variable. - llvm::DenseMap<BoolValue *, Variable> SubValsToVar; - // Store variable identifiers and value location of atomic booleans. - llvm::DenseMap<Variable, AtomicBoolValue *> Atomics; + // Map each sub-formula in `Vals` to a unique variable. + llvm::DenseMap<const Formula *, Variable> SubValsToVar; + // Store variable identifiers and Atom of atomic booleans. + llvm::DenseMap<Variable, Atom> Atomics; Variable NextVar = 1; { - std::queue<BoolValue *> UnprocessedSubVals; - for (BoolValue *Val : Vals) + std::queue<const Formula *> UnprocessedSubVals; + for (const Formula *Val : Vals) UnprocessedSubVals.push(Val); while (!UnprocessedSubVals.empty()) { Variable Var = NextVar; - BoolValue *Val = UnprocessedSubVals.front(); + const Formula *Val = UnprocessedSubVals.front(); UnprocessedSubVals.pop(); if (!SubValsToVar.try_emplace(Val, Var).second) continue; ++NextVar; - // Visit the sub-values of `Val`. - switch (Val->getKind()) { - case Value::Kind::Conjunction: { - auto *C = cast<ConjunctionValue>(Val); - UnprocessedSubVals.push(&C->getLeftSubValue()); - UnprocessedSubVals.push(&C->getRightSubValue()); - break; - } - case Value::Kind::Disjunction: { - auto *D = cast<DisjunctionValue>(Val); - UnprocessedSubVals.push(&D->getLeftSubValue()); - UnprocessedSubVals.push(&D->getRightSubValue()); - break; - } - case Value::Kind::Negation: { - auto *N = cast<NegationValue>(Val); - UnprocessedSubVals.push(&N->getSubVal()); - break; - } - case Value::Kind::Implication: { - auto *I = cast<ImplicationValue>(Val); - UnprocessedSubVals.push(&I->getLeftSubValue()); - UnprocessedSubVals.push(&I->getRightSubValue()); - break; - } - case Value::Kind::Biconditional: { - auto *B = cast<BiconditionalValue>(Val); - UnprocessedSubVals.push(&B->getLeftSubValue()); - UnprocessedSubVals.push(&B->getRightSubValue()); - break; - } - case Value::Kind::TopBool: - // Nothing more to do. This `TopBool` instance has already been mapped - // to a fresh solver variable (`NextVar`, above) and is thereafter - // anonymous. The solver never sees `Top`. - break; - case Value::Kind::AtomicBool: { - Atomics[Var] = cast<AtomicBoolValue>(Val); - break; - } - default: - llvm_unreachable("buildBooleanFormula: unhandled value kind"); - } + for (const Formula *F : Val->operands()) + UnprocessedSubVals.push(F); + if (Val->kind() == Formula::AtomRef) + Atomics[Var] = Val->getAtom(); } } - auto GetVar = [&SubValsToVar](const BoolValue *Val) { + auto GetVar = [&SubValsToVar](const Formula *Val) { auto ValIt = SubValsToVar.find(Val); assert(ValIt != SubValsToVar.end()); return ValIt->second; }; - BooleanFormula Formula(NextVar - 1, std::move(Atomics)); + CNFFormula CNF(NextVar - 1, std::move(Atomics)); std::vector<bool> ProcessedSubVals(NextVar, false); - // Add a conjunct for each variable that represents a top-level conjunction - // value in `Vals`. - for (BoolValue *Val : Vals) - Formula.addClause(posLit(GetVar(Val))); + // Add a conjunct for each variable that represents a top-level formula in + // `Vals`. + for (const Formula *Val : Vals) + CNF.addClause(posLit(GetVar(Val))); // Add conjuncts that represent the mapping between newly-created variables - // and their corresponding sub-values. - std::queue<BoolValue *> UnprocessedSubVals; - for (BoolValue *Val : Vals) + // and their corresponding sub-formulas. + std::queue<const Formula *> UnprocessedSubVals; + for (const Formula *Val : Vals) UnprocessedSubVals.push(Val); while (!UnprocessedSubVals.empty()) { - const BoolValue *Val = UnprocessedSubVals.front(); + const Formula *Val = UnprocessedSubVals.front(); UnprocessedSubVals.pop(); const Variable Var = GetVar(Val); @@ -276,117 +238,107 @@ BooleanFormula buildBooleanFormula(const llvm::DenseSet<BoolValue *> &Vals) { continue; ProcessedSubVals[Var] = true; - if (auto *C = dyn_cast<ConjunctionValue>(Val)) { - const Variable LeftSubVar = GetVar(&C->getLeftSubValue()); - const Variable RightSubVar = GetVar(&C->getRightSubValue()); + switch (Val->kind()) { + case Formula::AtomRef: + break; + case Formula::And: { + const Variable LHS = GetVar(Val->operands()[0]); + const Variable RHS = GetVar(Val->operands()[1]); - if (LeftSubVar == RightSubVar) { + if (LHS == RHS) { // `X <=> (A ^ A)` is equivalent to `(!X v A) ^ (X v !A)` which is // already in conjunctive normal form. Below we add each of the // conjuncts of the latter expression to the result. - Formula.addClause(negLit(Var), posLit(LeftSubVar)); - Formula.addClause(posLit(Var), negLit(LeftSubVar)); - - // Visit a sub-value of `Val` (pick any, they are identical). - UnprocessedSubVals.push(&C->getLeftSubValue()); + CNF.addClause(negLit(Var), posLit(LHS)); + CNF.addClause(posLit(Var), negLit(LHS)); } else { // `X <=> (A ^ B)` is equivalent to `(!X v A) ^ (!X v B) ^ (X v !A v !B)` // which is already in conjunctive normal form. Below we add each of the // conjuncts of the latter expression to the result. - Formula.addClause(negLit(Var), posLit(LeftSubVar)); - Formula.addClause(negLit(Var), posLit(RightSubVar)); - Formula.addClause(posLit(Var), negLit(LeftSubVar), negLit(RightSubVar)); - - // Visit the sub-values of `Val`. - UnprocessedSubVals.push(&C->getLeftSubValue()); - UnprocessedSubVals.push(&C->getRightSubValue()); + CNF.addClause(negLit(Var), posLit(LHS)); + CNF.addClause(negLit(Var), posLit(RHS)); + CNF.addClause(posLit(Var), negLit(LHS), negLit(RHS)); } - } else if (auto *D = dyn_cast<DisjunctionValue>(Val)) { - const Variable LeftSubVar = GetVar(&D->getLeftSubValue()); - const Variable RightSubVar = GetVar(&D->getRightSubValue()); + break; + } + case Formula::Or: { + const Variable LHS = GetVar(Val->operands()[0]); + const Variable RHS = GetVar(Val->operands()[1]); - if (LeftSubVar == RightSubVar) { + if (LHS == RHS) { // `X <=> (A v A)` is equivalent to `(!X v A) ^ (X v !A)` which is // already in conjunctive normal form. Below we add each of the // conjuncts of the latter expression to the result. - Formula.addClause(negLit(Var), posLit(LeftSubVar)); - Formula.addClause(posLit(Var), negLit(LeftSubVar)); - - // Visit a sub-value of `Val` (pick any, they are identical). - UnprocessedSubVals.push(&D->getLeftSubValue()); + CNF.addClause(negLit(Var), posLit(LHS)); + CNF.addClause(posLit(Var), negLit(LHS)); } else { - // `X <=> (A v B)` is equivalent to `(!X v A v B) ^ (X v !A) ^ (X v !B)` - // which is already in conjunctive normal form. Below we add each of the - // conjuncts of the latter expression to the result. - Formula.addClause(negLit(Var), posLit(LeftSubVar), posLit(RightSubVar)); - Formula.addClause(posLit(Var), negLit(LeftSubVar)); - Formula.addClause(posLit(Var), negLit(RightSubVar)); - - // Visit the sub-values of `Val`. - UnprocessedSubVals.push(&D->getLeftSubValue()); - UnprocessedSubVals.push(&D->getRightSubValue()); + // `X <=> (A v B)` is equivalent to `(!X v A v B) ^ (X v !A) ^ (X v + // !B)` which is already in conjunctive normal form. Below we add each + // of the conjuncts of the latter expression to the result. + CNF.addClause(negLit(Var), posLit(LHS), posLit(RHS)); + CNF.addClause(posLit(Var), negLit(LHS)); + CNF.addClause(posLit(Var), negLit(RHS)); } - } else if (auto *N = dyn_cast<NegationValue>(Val)) { - const Variable SubVar = GetVar(&N->getSubVal()); - - // `X <=> !Y` is equivalent to `(!X v !Y) ^ (X v Y)` which is already in - // conjunctive normal form. Below we add each of the conjuncts of the - // latter expression to the result. - Formula.addClause(negLit(Var), negLit(SubVar)); - Formula.addClause(posLit(Var), posLit(SubVar)); - - // Visit the sub-values of `Val`. - UnprocessedSubVals.push(&N->getSubVal()); - } else if (auto *I = dyn_cast<ImplicationValue>(Val)) { - const Variable LeftSubVar = GetVar(&I->getLeftSubValue()); - const Variable RightSubVar = GetVar(&I->getRightSubValue()); + break; + } + case Formula::Not: { + const Variable Operand = GetVar(Val->operands()[0]); + + // `X <=> !Y` is equivalent to `(!X v !Y) ^ (X v Y)` which is + // already in conjunctive normal form. Below we add each of the + // conjuncts of the latter expression to the result. + CNF.addClause(negLit(Var), negLit(Operand)); + CNF.addClause(posLit(Var), posLit(Operand)); + break; + } + case Formula::Implies: { + const Variable LHS = GetVar(Val->operands()[0]); + const Variable RHS = GetVar(Val->operands()[1]); // `X <=> (A => B)` is equivalent to // `(X v A) ^ (X v !B) ^ (!X v !A v B)` which is already in - // conjunctive normal form. Below we add each of the conjuncts of the - // latter expression to the result. - Formula.addClause(posLit(Var), posLit(LeftSubVar)); - Formula.addClause(posLit(Var), negLit(RightSubVar)); - Formula.addClause(negLit(Var), negLit(LeftSubVar), posLit(RightSubVar)); - - // Visit the sub-values of `Val`. - UnprocessedSubVals.push(&I->getLeftSubValue()); - UnprocessedSubVals.push(&I->getRightSubValue()); - } else if (auto *B = dyn_cast<BiconditionalValue>(Val)) { - const Variable LeftSubVar = GetVar(&B->getLeftSubValue()); - const Variable RightSubVar = GetVar(&B->getRightSubValue()); - - if (LeftSubVar == RightSubVar) { + // conjunctive normal form. Below we add each of the conjuncts of + // the latter expression to the result. + CNF.addClause(posLit(Var), posLit(LHS)); + CNF.addClause(posLit(Var), negLit(RHS)); + CNF.addClause(negLit(Var), negLit(LHS), posLit(RHS)); + break; + } + case Formula::Equal: { + const Variable LHS = GetVar(Val->operands()[0]); + const Variable RHS = GetVar(Val->operands()[1]); + + if (LHS == RHS) { // `X <=> (A <=> A)` is equvalent to `X` which is already in // conjunctive normal form. Below we add each of the conjuncts of the // latter expression to the result. - Formula.addClause(posLit(Var)); + CNF.addClause(posLit(Var)); // No need to visit the sub-values of `Val`. - } else { - // `X <=> (A <=> B)` is equivalent to - // `(X v A v B) ^ (X v !A v !B) ^ (!X v A v !B) ^ (!X v !A v B)` which is - // already in conjunctive normal form. Below we add each of the conjuncts - // of the latter expression to the result. - Formula.addClause(posLit(Var), posLit(LeftSubVar), posLit(RightSubVar)); - Formula.addClause(posLit(Var), negLit(LeftSubVar), negLit(RightSubVar)); - Formula.addClause(negLit(Var), posLit(LeftSubVar), negLit(RightSubVar)); - Formula.addClause(negLit(Var), negLit(LeftSubVar), posLit(RightSubVar)); - - // Visit the sub-values of `Val`. - UnprocessedSubVals.push(&B->getLeftSubValue()); - UnprocessedSubVals.push(&B->getRightSubValue()); + continue; } + // `X <=> (A <=> B)` is equivalent to + // `(X v A v B) ^ (X v !A v !B) ^ (!X v A v !B) ^ (!X v !A v B)` which + // is already in conjunctive normal form. Below we add each of the + // conjuncts of the latter expression to the result. + CNF.addClause(posLit(Var), posLit(LHS), posLit(RHS)); + CNF.addClause(posLit(Var), negLit(LHS), negLit(RHS)); + CNF.addClause(negLit(Var), posLit(LHS), negLit(RHS)); + CNF.addClause(negLit(Var), negLit(LHS), posLit(RHS)); + break; } + } + for (const Formula *Child : Val->operands()) + UnprocessedSubVals.push(Child); } - return Formula; + return CNF; } class WatchedLiteralsSolverImpl { /// A boolean formula in conjunctive normal form that the solver will attempt /// to prove satisfiable. The formula will be modified in the process. - BooleanFormula Formula; + CNFFormula CNF; /// The search for a satisfying assignment of the variables in `Formula` will /// proceed in levels, starting from 1 and going up to `Formula.LargestVar` @@ -438,9 +390,10 @@ class WatchedLiteralsSolverImpl { std::vector<Variable> ActiveVars; public: - explicit WatchedLiteralsSolverImpl(const llvm::DenseSet<BoolValue *> &Vals) - : Formula(buildBooleanFormula(Vals)), LevelVars(Formula.LargestVar + 1), - LevelStates(Formula.LargestVar + 1) { + explicit WatchedLiteralsSolverImpl( + const llvm::ArrayRef<const Formula *> &Vals) + : CNF(buildCNF(Vals)), LevelVars(CNF.LargestVar + 1), + LevelStates(CNF.LargestVar + 1) { assert(!Vals.empty()); // Initialize the state at the root level to a decision so that in @@ -449,25 +402,31 @@ public: LevelStates[0] = State::Decision; // Initialize all variables as unassigned. - VarAssignments.resize(Formula.LargestVar + 1, Assignment::Unassigned); + VarAssignments.resize(CNF.LargestVar + 1, Assignment::Unassigned); // Initialize the active variables. - for (Variable Var = Formula.LargestVar; Var != NullVar; --Var) { + for (Variable Var = CNF.LargestVar; Var != NullVar; --Var) { if (isWatched(posLit(Var)) || isWatched(negLit(Var))) ActiveVars.push_back(Var); } } - Solver::Result solve() && { + // Returns the `Result` and the number of iterations "remaining" from + // `MaxIterations` (that is, `MaxIterations` - iterations in this call). + std::pair<Solver::Result, std::int64_t> solve(std::int64_t MaxIterations) && { size_t I = 0; while (I < ActiveVars.size()) { + if (MaxIterations == 0) + return std::make_pair(Solver::Result::TimedOut(), 0); + --MaxIterations; + // Assert that the following invariants hold: // 1. All active variables are unassigned. // 2. All active variables form watched literals. // 3. Unassigned variables that form watched literals are active. // FIXME: Consider replacing these with test cases that fail if the any // of the invariants is broken. That might not be easy due to the - // transformations performed by `buildBooleanFormula`. + // transformations performed by `buildCNF`. assert(activeVarsAreUnassigned()); assert(activeVarsFormWatchedLiterals()); assert(unassignedVarsFormingWatchedLiteralsAreActive()); @@ -487,7 +446,7 @@ public: // If the root level is reached, then all possible assignments lead to // a conflict. if (Level == 0) - return Solver::Result::Unsatisfiable(); + return std::make_pair(Solver::Result::Unsatisfiable(), MaxIterations); // Otherwise, take the other branch at the most recent level where a // decision was made. @@ -544,16 +503,14 @@ public: ++I; } } - return Solver::Result::Satisfiable(buildSolution()); + return std::make_pair(Solver::Result::Satisfiable(buildSolution()), MaxIterations); } private: - /// Returns a satisfying truth assignment to the atomic values in the boolean - /// formula. - llvm::DenseMap<AtomicBoolValue *, Solver::Result::Assignment> - buildSolution() { - llvm::DenseMap<AtomicBoolValue *, Solver::Result::Assignment> Solution; - for (auto &Atomic : Formula.Atomics) { + /// Returns a satisfying truth assignment to the atoms in the boolean formula. + llvm::DenseMap<Atom, Solver::Result::Assignment> buildSolution() { + llvm::DenseMap<Atom, Solver::Result::Assignment> Solution; + for (auto &Atomic : CNF.Atomics) { // A variable may have a definite true/false assignment, or it may be // unassigned indicating its truth value does not affect the result of // the formula. Unassigned variables are assigned to true as a default. @@ -589,24 +546,24 @@ private: const Literal FalseLit = VarAssignments[Var] == Assignment::AssignedTrue ? negLit(Var) : posLit(Var); - ClauseID FalseLitWatcher = Formula.WatchedHead[FalseLit]; - Formula.WatchedHead[FalseLit] = NullClause; + ClauseID FalseLitWatcher = CNF.WatchedHead[FalseLit]; + CNF.WatchedHead[FalseLit] = NullClause; while (FalseLitWatcher != NullClause) { - const ClauseID NextFalseLitWatcher = Formula.NextWatched[FalseLitWatcher]; + const ClauseID NextFalseLitWatcher = CNF.NextWatched[FalseLitWatcher]; // Pick the first non-false literal as the new watched literal. - const size_t FalseLitWatcherStart = Formula.ClauseStarts[FalseLitWatcher]; + const size_t FalseLitWatcherStart = CNF.ClauseStarts[FalseLitWatcher]; size_t NewWatchedLitIdx = FalseLitWatcherStart + 1; - while (isCurrentlyFalse(Formula.Clauses[NewWatchedLitIdx])) + while (isCurrentlyFalse(CNF.Clauses[NewWatchedLitIdx])) ++NewWatchedLitIdx; - const Literal NewWatchedLit = Formula.Clauses[NewWatchedLitIdx]; + const Literal NewWatchedLit = CNF.Clauses[NewWatchedLitIdx]; const Variable NewWatchedLitVar = var(NewWatchedLit); // Swap the old watched literal for the new one in `FalseLitWatcher` to // maintain the invariant that the watched literal is at the beginning of // the clause. - Formula.Clauses[NewWatchedLitIdx] = FalseLit; - Formula.Clauses[FalseLitWatcherStart] = NewWatchedLit; + CNF.Clauses[NewWatchedLitIdx] = FalseLit; + CNF.Clauses[FalseLitWatcherStart] = NewWatchedLit; // If the new watched literal isn't watched by any other clause and its // variable isn't assigned we need to add it to the active variables. @@ -614,8 +571,8 @@ private: VarAssignments[NewWatchedLitVar] == Assignment::Unassigned) ActiveVars.push_back(NewWatchedLitVar); - Formula.NextWatched[FalseLitWatcher] = Formula.WatchedHead[NewWatchedLit]; - Formula.WatchedHead[NewWatchedLit] = FalseLitWatcher; + CNF.NextWatched[FalseLitWatcher] = CNF.WatchedHead[NewWatchedLit]; + CNF.WatchedHead[NewWatchedLit] = FalseLitWatcher; // Go to the next clause that watches `FalseLit`. FalseLitWatcher = NextFalseLitWatcher; @@ -625,16 +582,15 @@ private: /// Returns true if and only if one of the clauses that watch `Lit` is a unit /// clause. bool watchedByUnitClause(Literal Lit) const { - for (ClauseID LitWatcher = Formula.WatchedHead[Lit]; - LitWatcher != NullClause; - LitWatcher = Formula.NextWatched[LitWatcher]) { - llvm::ArrayRef<Literal> Clause = Formula.clauseLiterals(LitWatcher); + for (ClauseID LitWatcher = CNF.WatchedHead[Lit]; LitWatcher != NullClause; + LitWatcher = CNF.NextWatched[LitWatcher]) { + llvm::ArrayRef<Literal> Clause = CNF.clauseLiterals(LitWatcher); // Assert the invariant that the watched literal is always the first one // in the clause. // FIXME: Consider replacing this with a test case that fails if the // invariant is broken by `updateWatchedLiterals`. That might not be easy - // due to the transformations performed by `buildBooleanFormula`. + // due to the transformations performed by `buildCNF`. assert(Clause.front() == Lit); if (isUnit(Clause)) @@ -658,7 +614,7 @@ private: /// Returns true if and only if `Lit` is watched by a clause in `Formula`. bool isWatched(Literal Lit) const { - return Formula.WatchedHead[Lit] != NullClause; + return CNF.WatchedHead[Lit] != NullClause; } /// Returns an assignment for an unassigned variable. @@ -671,8 +627,8 @@ private: /// Returns a set of all watched literals. llvm::DenseSet<Literal> watchedLiterals() const { llvm::DenseSet<Literal> WatchedLiterals; - for (Literal Lit = 2; Lit < Formula.WatchedHead.size(); Lit++) { - if (Formula.WatchedHead[Lit] == NullClause) + for (Literal Lit = 2; Lit < CNF.WatchedHead.size(); Lit++) { + if (CNF.WatchedHead[Lit] == NullClause) continue; WatchedLiterals.insert(Lit); } @@ -712,9 +668,14 @@ private: } }; -Solver::Result WatchedLiteralsSolver::solve(llvm::DenseSet<BoolValue *> Vals) { - return Vals.empty() ? Solver::Result::Satisfiable({{}}) - : WatchedLiteralsSolverImpl(Vals).solve(); +Solver::Result +WatchedLiteralsSolver::solve(llvm::ArrayRef<const Formula *> Vals) { + if (Vals.empty()) + return Solver::Result::Satisfiable({{}}); + auto [Res, Iterations] = + WatchedLiteralsSolverImpl(Vals).solve(MaxIterations); + MaxIterations = Iterations; + return Res; } } // namespace dataflow |
