xref: /freebsd/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp (revision 258a0d760aa8b42899a000e30f610f900a402556)
1 //===- WatchedLiteralsSolver.cpp --------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 //  This file defines a SAT solver implementation that can be used by dataflow
10 //  analyses.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include <cassert>
15 #include <cstdint>
16 #include <iterator>
17 #include <queue>
18 #include <vector>
19 
20 #include "clang/Analysis/FlowSensitive/Solver.h"
21 #include "clang/Analysis/FlowSensitive/Value.h"
22 #include "clang/Analysis/FlowSensitive/WatchedLiteralsSolver.h"
23 #include "llvm/ADT/DenseMap.h"
24 #include "llvm/ADT/DenseSet.h"
25 #include "llvm/ADT/STLExtras.h"
26 
27 namespace clang {
28 namespace dataflow {
29 
30 // `WatchedLiteralsSolver` is an implementation of Algorithm D from Knuth's
31 // The Art of Computer Programming Volume 4: Satisfiability, Fascicle 6. It is
32 // based on the backtracking DPLL algorithm [1], keeps references to a single
33 // "watched" literal per clause, and uses a set of "active" variables to perform
34 // unit propagation.
35 //
36 // The solver expects that its input is a boolean formula in conjunctive normal
37 // form that consists of clauses of at least one literal. A literal is either a
38 // boolean variable or its negation. Below we define types, data structures, and
39 // utilities that are used to represent boolean formulas in conjunctive normal
40 // form.
41 //
42 // [1] https://en.wikipedia.org/wiki/DPLL_algorithm
43 
44 /// Boolean variables are represented as positive integers.
45 using Variable = uint32_t;
46 
47 /// A null boolean variable is used as a placeholder in various data structures
48 /// and algorithms.
49 static constexpr Variable NullVar = 0;
50 
51 /// Literals are represented as positive integers. Specifically, for a boolean
52 /// variable `V` that is represented as the positive integer `I`, the positive
53 /// literal `V` is represented as the integer `2*I` and the negative literal
54 /// `!V` is represented as the integer `2*I+1`.
55 using Literal = uint32_t;
56 
57 /// A null literal is used as a placeholder in various data structures and
58 /// algorithms.
59 static constexpr Literal NullLit = 0;
60 
61 /// Returns the positive literal `V`.
62 static constexpr Literal posLit(Variable V) { return 2 * V; }
63 
64 /// Returns the negative literal `!V`.
65 static constexpr Literal negLit(Variable V) { return 2 * V + 1; }
66 
67 /// Returns the negated literal `!L`.
68 static constexpr Literal notLit(Literal L) { return L ^ 1; }
69 
70 /// Returns the variable of `L`.
71 static constexpr Variable var(Literal L) { return L >> 1; }
72 
73 /// Clause identifiers are represented as positive integers.
74 using ClauseID = uint32_t;
75 
76 /// A null clause identifier is used as a placeholder in various data structures
77 /// and algorithms.
78 static constexpr ClauseID NullClause = 0;
79 
80 /// A boolean formula in conjunctive normal form.
81 struct BooleanFormula {
82   /// `LargestVar` is equal to the largest positive integer that represents a
83   /// variable in the formula.
84   const Variable LargestVar;
85 
86   /// Literals of all clauses in the formula.
87   ///
88   /// The element at index 0 stands for the literal in the null clause. It is
89   /// set to 0 and isn't used. Literals of clauses in the formula start from the
90   /// element at index 1.
91   ///
92   /// For example, for the formula `(L1 v L2) ^ (L2 v L3 v L4)` the elements of
93   /// `Clauses` will be `[0, L1, L2, L2, L3, L4]`.
94   std::vector<Literal> Clauses;
95 
96   /// Start indices of clauses of the formula in `Clauses`.
97   ///
98   /// The element at index 0 stands for the start index of the null clause. It
99   /// is set to 0 and isn't used. Start indices of clauses in the formula start
100   /// from the element at index 1.
101   ///
102   /// For example, for the formula `(L1 v L2) ^ (L2 v L3 v L4)` the elements of
103   /// `ClauseStarts` will be `[0, 1, 3]`. Note that the literals of the first
104   /// clause always start at index 1. The start index for the literals of the
105   /// second clause depends on the size of the first clause and so on.
106   std::vector<size_t> ClauseStarts;
107 
108   /// Maps literals (indices of the vector) to clause identifiers (elements of
109   /// the vector) that watch the respective literals.
110   ///
111   /// For a given clause, its watched literal is always its first literal in
112   /// `Clauses`. This invariant is maintained when watched literals change.
113   std::vector<ClauseID> WatchedHead;
114 
115   /// Maps clause identifiers (elements of the vector) to identifiers of other
116   /// clauses that watch the same literals, forming a set of linked lists.
117   ///
118   /// The element at index 0 stands for the identifier of the clause that
119   /// follows the null clause. It is set to 0 and isn't used. Identifiers of
120   /// clauses in the formula start from the element at index 1.
121   std::vector<ClauseID> NextWatched;
122 
123   /// Stores the variable identifier and value location for atomic booleans in
124   /// the formula.
125   llvm::DenseMap<Variable, AtomicBoolValue *> Atomics;
126 
127   explicit BooleanFormula(Variable LargestVar,
128                           llvm::DenseMap<Variable, AtomicBoolValue *> Atomics)
129       : LargestVar(LargestVar), Atomics(std::move(Atomics)) {
130     Clauses.push_back(0);
131     ClauseStarts.push_back(0);
132     NextWatched.push_back(0);
133     const size_t NumLiterals = 2 * LargestVar + 1;
134     WatchedHead.resize(NumLiterals + 1, 0);
135   }
136 
137   /// Adds the `L1 v L2 v L3` clause to the formula. If `L2` or `L3` are
138   /// `NullLit` they are respectively omitted from the clause.
139   ///
140   /// Requirements:
141   ///
142   ///  `L1` must not be `NullLit`.
143   ///
144   ///  All literals in the input that are not `NullLit` must be distinct.
145   void addClause(Literal L1, Literal L2 = NullLit, Literal L3 = NullLit) {
146     // The literals are guaranteed to be distinct from properties of BoolValue
147     // and the construction in `buildBooleanFormula`.
148     assert(L1 != NullLit && L1 != L2 && L1 != L3 &&
149            (L2 != L3 || L2 == NullLit));
150 
151     const ClauseID C = ClauseStarts.size();
152     const size_t S = Clauses.size();
153     ClauseStarts.push_back(S);
154 
155     Clauses.push_back(L1);
156     if (L2 != NullLit)
157       Clauses.push_back(L2);
158     if (L3 != NullLit)
159       Clauses.push_back(L3);
160 
161     // Designate the first literal as the "watched" literal of the clause.
162     NextWatched.push_back(WatchedHead[L1]);
163     WatchedHead[L1] = C;
164   }
165 
166   /// Returns the number of literals in clause `C`.
167   size_t clauseSize(ClauseID C) const {
168     return C == ClauseStarts.size() - 1 ? Clauses.size() - ClauseStarts[C]
169                                         : ClauseStarts[C + 1] - ClauseStarts[C];
170   }
171 
172   /// Returns the literals of clause `C`.
173   llvm::ArrayRef<Literal> clauseLiterals(ClauseID C) const {
174     return llvm::ArrayRef<Literal>(&Clauses[ClauseStarts[C]], clauseSize(C));
175   }
176 };
177 
178 /// Converts the conjunction of `Vals` into a formula in conjunctive normal
179 /// form where each clause has at least one and at most three literals.
180 BooleanFormula buildBooleanFormula(const llvm::DenseSet<BoolValue *> &Vals) {
181   // The general strategy of the algorithm implemented below is to map each
182   // of the sub-values in `Vals` to a unique variable and use these variables in
183   // the resulting CNF expression to avoid exponential blow up. The number of
184   // literals in the resulting formula is guaranteed to be linear in the number
185   // of sub-values in `Vals`.
186 
187   // Map each sub-value in `Vals` to a unique variable.
188   llvm::DenseMap<BoolValue *, Variable> SubValsToVar;
189   // Store variable identifiers and value location of atomic booleans.
190   llvm::DenseMap<Variable, AtomicBoolValue *> Atomics;
191   Variable NextVar = 1;
192   {
193     std::queue<BoolValue *> UnprocessedSubVals;
194     for (BoolValue *Val : Vals)
195       UnprocessedSubVals.push(Val);
196     while (!UnprocessedSubVals.empty()) {
197       Variable Var = NextVar;
198       BoolValue *Val = UnprocessedSubVals.front();
199       UnprocessedSubVals.pop();
200 
201       if (!SubValsToVar.try_emplace(Val, Var).second)
202         continue;
203       ++NextVar;
204 
205       // Visit the sub-values of `Val`.
206       switch (Val->getKind()) {
207       case Value::Kind::Conjunction: {
208         auto *C = cast<ConjunctionValue>(Val);
209         UnprocessedSubVals.push(&C->getLeftSubValue());
210         UnprocessedSubVals.push(&C->getRightSubValue());
211         break;
212       }
213       case Value::Kind::Disjunction: {
214         auto *D = cast<DisjunctionValue>(Val);
215         UnprocessedSubVals.push(&D->getLeftSubValue());
216         UnprocessedSubVals.push(&D->getRightSubValue());
217         break;
218       }
219       case Value::Kind::Negation: {
220         auto *N = cast<NegationValue>(Val);
221         UnprocessedSubVals.push(&N->getSubVal());
222         break;
223       }
224       case Value::Kind::Implication: {
225         auto *I = cast<ImplicationValue>(Val);
226         UnprocessedSubVals.push(&I->getLeftSubValue());
227         UnprocessedSubVals.push(&I->getRightSubValue());
228         break;
229       }
230       case Value::Kind::Biconditional: {
231         auto *B = cast<BiconditionalValue>(Val);
232         UnprocessedSubVals.push(&B->getLeftSubValue());
233         UnprocessedSubVals.push(&B->getRightSubValue());
234         break;
235       }
236       case Value::Kind::TopBool:
237         // Nothing more to do. This `TopBool` instance has already been mapped
238         // to a fresh solver variable (`NextVar`, above) and is thereafter
239         // anonymous. The solver never sees `Top`.
240         break;
241       case Value::Kind::AtomicBool: {
242         Atomics[Var] = cast<AtomicBoolValue>(Val);
243         break;
244       }
245       default:
246         llvm_unreachable("buildBooleanFormula: unhandled value kind");
247       }
248     }
249   }
250 
251   auto GetVar = [&SubValsToVar](const BoolValue *Val) {
252     auto ValIt = SubValsToVar.find(Val);
253     assert(ValIt != SubValsToVar.end());
254     return ValIt->second;
255   };
256 
257   BooleanFormula Formula(NextVar - 1, std::move(Atomics));
258   std::vector<bool> ProcessedSubVals(NextVar, false);
259 
260   // Add a conjunct for each variable that represents a top-level conjunction
261   // value in `Vals`.
262   for (BoolValue *Val : Vals)
263     Formula.addClause(posLit(GetVar(Val)));
264 
265   // Add conjuncts that represent the mapping between newly-created variables
266   // and their corresponding sub-values.
267   std::queue<BoolValue *> UnprocessedSubVals;
268   for (BoolValue *Val : Vals)
269     UnprocessedSubVals.push(Val);
270   while (!UnprocessedSubVals.empty()) {
271     const BoolValue *Val = UnprocessedSubVals.front();
272     UnprocessedSubVals.pop();
273     const Variable Var = GetVar(Val);
274 
275     if (ProcessedSubVals[Var])
276       continue;
277     ProcessedSubVals[Var] = true;
278 
279     if (auto *C = dyn_cast<ConjunctionValue>(Val)) {
280       const Variable LeftSubVar = GetVar(&C->getLeftSubValue());
281       const Variable RightSubVar = GetVar(&C->getRightSubValue());
282 
283       if (LeftSubVar == RightSubVar) {
284         // `X <=> (A ^ A)` is equivalent to `(!X v A) ^ (X v !A)` which is
285         // already in conjunctive normal form. Below we add each of the
286         // conjuncts of the latter expression to the result.
287         Formula.addClause(negLit(Var), posLit(LeftSubVar));
288         Formula.addClause(posLit(Var), negLit(LeftSubVar));
289 
290         // Visit a sub-value of `Val` (pick any, they are identical).
291         UnprocessedSubVals.push(&C->getLeftSubValue());
292       } else {
293         // `X <=> (A ^ B)` is equivalent to `(!X v A) ^ (!X v B) ^ (X v !A v !B)`
294         // which is already in conjunctive normal form. Below we add each of the
295         // conjuncts of the latter expression to the result.
296         Formula.addClause(negLit(Var), posLit(LeftSubVar));
297         Formula.addClause(negLit(Var), posLit(RightSubVar));
298         Formula.addClause(posLit(Var), negLit(LeftSubVar), negLit(RightSubVar));
299 
300         // Visit the sub-values of `Val`.
301         UnprocessedSubVals.push(&C->getLeftSubValue());
302         UnprocessedSubVals.push(&C->getRightSubValue());
303       }
304     } else if (auto *D = dyn_cast<DisjunctionValue>(Val)) {
305       const Variable LeftSubVar = GetVar(&D->getLeftSubValue());
306       const Variable RightSubVar = GetVar(&D->getRightSubValue());
307 
308       if (LeftSubVar == RightSubVar) {
309         // `X <=> (A v A)` is equivalent to `(!X v A) ^ (X v !A)` which is
310         // already in conjunctive normal form. Below we add each of the
311         // conjuncts of the latter expression to the result.
312         Formula.addClause(negLit(Var), posLit(LeftSubVar));
313         Formula.addClause(posLit(Var), negLit(LeftSubVar));
314 
315         // Visit a sub-value of `Val` (pick any, they are identical).
316         UnprocessedSubVals.push(&D->getLeftSubValue());
317       } else {
318         // `X <=> (A v B)` is equivalent to `(!X v A v B) ^ (X v !A) ^ (X v !B)`
319         // which is already in conjunctive normal form. Below we add each of the
320         // conjuncts of the latter expression to the result.
321         Formula.addClause(negLit(Var), posLit(LeftSubVar), posLit(RightSubVar));
322         Formula.addClause(posLit(Var), negLit(LeftSubVar));
323         Formula.addClause(posLit(Var), negLit(RightSubVar));
324 
325         // Visit the sub-values of `Val`.
326         UnprocessedSubVals.push(&D->getLeftSubValue());
327         UnprocessedSubVals.push(&D->getRightSubValue());
328       }
329     } else if (auto *N = dyn_cast<NegationValue>(Val)) {
330       const Variable SubVar = GetVar(&N->getSubVal());
331 
332       // `X <=> !Y` is equivalent to `(!X v !Y) ^ (X v Y)` which is already in
333       // conjunctive normal form. Below we add each of the conjuncts of the
334       // latter expression to the result.
335       Formula.addClause(negLit(Var), negLit(SubVar));
336       Formula.addClause(posLit(Var), posLit(SubVar));
337 
338       // Visit the sub-values of `Val`.
339       UnprocessedSubVals.push(&N->getSubVal());
340     } else if (auto *I = dyn_cast<ImplicationValue>(Val)) {
341       const Variable LeftSubVar = GetVar(&I->getLeftSubValue());
342       const Variable RightSubVar = GetVar(&I->getRightSubValue());
343 
344       // `X <=> (A => B)` is equivalent to
345       // `(X v A) ^ (X v !B) ^ (!X v !A v B)` which is already in
346       // conjunctive normal form. Below we add each of the conjuncts of the
347       // latter expression to the result.
348       Formula.addClause(posLit(Var), posLit(LeftSubVar));
349       Formula.addClause(posLit(Var), negLit(RightSubVar));
350       Formula.addClause(negLit(Var), negLit(LeftSubVar), posLit(RightSubVar));
351 
352       // Visit the sub-values of `Val`.
353       UnprocessedSubVals.push(&I->getLeftSubValue());
354       UnprocessedSubVals.push(&I->getRightSubValue());
355     } else if (auto *B = dyn_cast<BiconditionalValue>(Val)) {
356       const Variable LeftSubVar = GetVar(&B->getLeftSubValue());
357       const Variable RightSubVar = GetVar(&B->getRightSubValue());
358 
359       if (LeftSubVar == RightSubVar) {
360         // `X <=> (A <=> A)` is equvalent to `X` which is already in
361         // conjunctive normal form. Below we add each of the conjuncts of the
362         // latter expression to the result.
363         Formula.addClause(posLit(Var));
364 
365         // No need to visit the sub-values of `Val`.
366       } else {
367         // `X <=> (A <=> B)` is equivalent to
368         // `(X v A v B) ^ (X v !A v !B) ^ (!X v A v !B) ^ (!X v !A v B)` which is
369         // already in conjunctive normal form. Below we add each of the conjuncts
370         // of the latter expression to the result.
371         Formula.addClause(posLit(Var), posLit(LeftSubVar), posLit(RightSubVar));
372         Formula.addClause(posLit(Var), negLit(LeftSubVar), negLit(RightSubVar));
373         Formula.addClause(negLit(Var), posLit(LeftSubVar), negLit(RightSubVar));
374         Formula.addClause(negLit(Var), negLit(LeftSubVar), posLit(RightSubVar));
375 
376         // Visit the sub-values of `Val`.
377         UnprocessedSubVals.push(&B->getLeftSubValue());
378         UnprocessedSubVals.push(&B->getRightSubValue());
379       }
380     }
381   }
382 
383   return Formula;
384 }
385 
386 class WatchedLiteralsSolverImpl {
387   /// A boolean formula in conjunctive normal form that the solver will attempt
388   /// to prove satisfiable. The formula will be modified in the process.
389   BooleanFormula Formula;
390 
391   /// The search for a satisfying assignment of the variables in `Formula` will
392   /// proceed in levels, starting from 1 and going up to `Formula.LargestVar`
393   /// (inclusive). The current level is stored in `Level`. At each level the
394   /// solver will assign a value to an unassigned variable. If this leads to a
395   /// consistent partial assignment, `Level` will be incremented. Otherwise, if
396   /// it results in a conflict, the solver will backtrack by decrementing
397   /// `Level` until it reaches the most recent level where a decision was made.
398   size_t Level = 0;
399 
400   /// Maps levels (indices of the vector) to variables (elements of the vector)
401   /// that are assigned values at the respective levels.
402   ///
403   /// The element at index 0 isn't used. Variables start from the element at
404   /// index 1.
405   std::vector<Variable> LevelVars;
406 
407   /// State of the solver at a particular level.
408   enum class State : uint8_t {
409     /// Indicates that the solver made a decision.
410     Decision = 0,
411 
412     /// Indicates that the solver made a forced move.
413     Forced = 1,
414   };
415 
416   /// State of the solver at a particular level. It keeps track of previous
417   /// decisions that the solver can refer to when backtracking.
418   ///
419   /// The element at index 0 isn't used. States start from the element at index
420   /// 1.
421   std::vector<State> LevelStates;
422 
423   enum class Assignment : int8_t {
424     Unassigned = -1,
425     AssignedFalse = 0,
426     AssignedTrue = 1
427   };
428 
429   /// Maps variables (indices of the vector) to their assignments (elements of
430   /// the vector).
431   ///
432   /// The element at index 0 isn't used. Variable assignments start from the
433   /// element at index 1.
434   std::vector<Assignment> VarAssignments;
435 
436   /// A set of unassigned variables that appear in watched literals in
437   /// `Formula`. The vector is guaranteed to contain unique elements.
438   std::vector<Variable> ActiveVars;
439 
440 public:
441   explicit WatchedLiteralsSolverImpl(const llvm::DenseSet<BoolValue *> &Vals)
442       : Formula(buildBooleanFormula(Vals)), LevelVars(Formula.LargestVar + 1),
443         LevelStates(Formula.LargestVar + 1) {
444     assert(!Vals.empty());
445 
446     // Initialize the state at the root level to a decision so that in
447     // `reverseForcedMoves` we don't have to check that `Level >= 0` on each
448     // iteration.
449     LevelStates[0] = State::Decision;
450 
451     // Initialize all variables as unassigned.
452     VarAssignments.resize(Formula.LargestVar + 1, Assignment::Unassigned);
453 
454     // Initialize the active variables.
455     for (Variable Var = Formula.LargestVar; Var != NullVar; --Var) {
456       if (isWatched(posLit(Var)) || isWatched(negLit(Var)))
457         ActiveVars.push_back(Var);
458     }
459   }
460 
461   Solver::Result solve() && {
462     size_t I = 0;
463     while (I < ActiveVars.size()) {
464       // Assert that the following invariants hold:
465       // 1. All active variables are unassigned.
466       // 2. All active variables form watched literals.
467       // 3. Unassigned variables that form watched literals are active.
468       // FIXME: Consider replacing these with test cases that fail if the any
469       // of the invariants is broken. That might not be easy due to the
470       // transformations performed by `buildBooleanFormula`.
471       assert(activeVarsAreUnassigned());
472       assert(activeVarsFormWatchedLiterals());
473       assert(unassignedVarsFormingWatchedLiteralsAreActive());
474 
475       const Variable ActiveVar = ActiveVars[I];
476 
477       // Look for unit clauses that contain the active variable.
478       const bool unitPosLit = watchedByUnitClause(posLit(ActiveVar));
479       const bool unitNegLit = watchedByUnitClause(negLit(ActiveVar));
480       if (unitPosLit && unitNegLit) {
481         // We found a conflict!
482 
483         // Backtrack and rewind the `Level` until the most recent non-forced
484         // assignment.
485         reverseForcedMoves();
486 
487         // If the root level is reached, then all possible assignments lead to
488         // a conflict.
489         if (Level == 0)
490           return Solver::Result::Unsatisfiable();
491 
492         // Otherwise, take the other branch at the most recent level where a
493         // decision was made.
494         LevelStates[Level] = State::Forced;
495         const Variable Var = LevelVars[Level];
496         VarAssignments[Var] = VarAssignments[Var] == Assignment::AssignedTrue
497                                   ? Assignment::AssignedFalse
498                                   : Assignment::AssignedTrue;
499 
500         updateWatchedLiterals();
501       } else if (unitPosLit || unitNegLit) {
502         // We found a unit clause! The value of its unassigned variable is
503         // forced.
504         ++Level;
505 
506         LevelVars[Level] = ActiveVar;
507         LevelStates[Level] = State::Forced;
508         VarAssignments[ActiveVar] =
509             unitPosLit ? Assignment::AssignedTrue : Assignment::AssignedFalse;
510 
511         // Remove the variable that was just assigned from the set of active
512         // variables.
513         if (I + 1 < ActiveVars.size()) {
514           // Replace the variable that was just assigned with the last active
515           // variable for efficient removal.
516           ActiveVars[I] = ActiveVars.back();
517         } else {
518           // This was the last active variable. Repeat the process from the
519           // beginning.
520           I = 0;
521         }
522         ActiveVars.pop_back();
523 
524         updateWatchedLiterals();
525       } else if (I + 1 == ActiveVars.size()) {
526         // There are no remaining unit clauses in the formula! Make a decision
527         // for one of the active variables at the current level.
528         ++Level;
529 
530         LevelVars[Level] = ActiveVar;
531         LevelStates[Level] = State::Decision;
532         VarAssignments[ActiveVar] = decideAssignment(ActiveVar);
533 
534         // Remove the variable that was just assigned from the set of active
535         // variables.
536         ActiveVars.pop_back();
537 
538         updateWatchedLiterals();
539 
540         // This was the last active variable. Repeat the process from the
541         // beginning.
542         I = 0;
543       } else {
544         ++I;
545       }
546     }
547     return Solver::Result::Satisfiable(buildSolution());
548   }
549 
550 private:
551   /// Returns a satisfying truth assignment to the atomic values in the boolean
552   /// formula.
553   llvm::DenseMap<AtomicBoolValue *, Solver::Result::Assignment>
554   buildSolution() {
555     llvm::DenseMap<AtomicBoolValue *, Solver::Result::Assignment> Solution;
556     for (auto &Atomic : Formula.Atomics) {
557       // A variable may have a definite true/false assignment, or it may be
558       // unassigned indicating its truth value does not affect the result of
559       // the formula. Unassigned variables are assigned to true as a default.
560       Solution[Atomic.second] =
561           VarAssignments[Atomic.first] == Assignment::AssignedFalse
562               ? Solver::Result::Assignment::AssignedFalse
563               : Solver::Result::Assignment::AssignedTrue;
564     }
565     return Solution;
566   }
567 
568   /// Reverses forced moves until the most recent level where a decision was
569   /// made on the assignment of a variable.
570   void reverseForcedMoves() {
571     for (; LevelStates[Level] == State::Forced; --Level) {
572       const Variable Var = LevelVars[Level];
573 
574       VarAssignments[Var] = Assignment::Unassigned;
575 
576       // If the variable that we pass through is watched then we add it to the
577       // active variables.
578       if (isWatched(posLit(Var)) || isWatched(negLit(Var)))
579         ActiveVars.push_back(Var);
580     }
581   }
582 
583   /// Updates watched literals that are affected by a variable assignment.
584   void updateWatchedLiterals() {
585     const Variable Var = LevelVars[Level];
586 
587     // Update the watched literals of clauses that currently watch the literal
588     // that falsifies `Var`.
589     const Literal FalseLit = VarAssignments[Var] == Assignment::AssignedTrue
590                                  ? negLit(Var)
591                                  : posLit(Var);
592     ClauseID FalseLitWatcher = Formula.WatchedHead[FalseLit];
593     Formula.WatchedHead[FalseLit] = NullClause;
594     while (FalseLitWatcher != NullClause) {
595       const ClauseID NextFalseLitWatcher = Formula.NextWatched[FalseLitWatcher];
596 
597       // Pick the first non-false literal as the new watched literal.
598       const size_t FalseLitWatcherStart = Formula.ClauseStarts[FalseLitWatcher];
599       size_t NewWatchedLitIdx = FalseLitWatcherStart + 1;
600       while (isCurrentlyFalse(Formula.Clauses[NewWatchedLitIdx]))
601         ++NewWatchedLitIdx;
602       const Literal NewWatchedLit = Formula.Clauses[NewWatchedLitIdx];
603       const Variable NewWatchedLitVar = var(NewWatchedLit);
604 
605       // Swap the old watched literal for the new one in `FalseLitWatcher` to
606       // maintain the invariant that the watched literal is at the beginning of
607       // the clause.
608       Formula.Clauses[NewWatchedLitIdx] = FalseLit;
609       Formula.Clauses[FalseLitWatcherStart] = NewWatchedLit;
610 
611       // If the new watched literal isn't watched by any other clause and its
612       // variable isn't assigned we need to add it to the active variables.
613       if (!isWatched(NewWatchedLit) && !isWatched(notLit(NewWatchedLit)) &&
614           VarAssignments[NewWatchedLitVar] == Assignment::Unassigned)
615         ActiveVars.push_back(NewWatchedLitVar);
616 
617       Formula.NextWatched[FalseLitWatcher] = Formula.WatchedHead[NewWatchedLit];
618       Formula.WatchedHead[NewWatchedLit] = FalseLitWatcher;
619 
620       // Go to the next clause that watches `FalseLit`.
621       FalseLitWatcher = NextFalseLitWatcher;
622     }
623   }
624 
625   /// Returns true if and only if one of the clauses that watch `Lit` is a unit
626   /// clause.
627   bool watchedByUnitClause(Literal Lit) const {
628     for (ClauseID LitWatcher = Formula.WatchedHead[Lit];
629          LitWatcher != NullClause;
630          LitWatcher = Formula.NextWatched[LitWatcher]) {
631       llvm::ArrayRef<Literal> Clause = Formula.clauseLiterals(LitWatcher);
632 
633       // Assert the invariant that the watched literal is always the first one
634       // in the clause.
635       // FIXME: Consider replacing this with a test case that fails if the
636       // invariant is broken by `updateWatchedLiterals`. That might not be easy
637       // due to the transformations performed by `buildBooleanFormula`.
638       assert(Clause.front() == Lit);
639 
640       if (isUnit(Clause))
641         return true;
642     }
643     return false;
644   }
645 
646   /// Returns true if and only if `Clause` is a unit clause.
647   bool isUnit(llvm::ArrayRef<Literal> Clause) const {
648     return llvm::all_of(Clause.drop_front(),
649                         [this](Literal L) { return isCurrentlyFalse(L); });
650   }
651 
652   /// Returns true if and only if `Lit` evaluates to `false` in the current
653   /// partial assignment.
654   bool isCurrentlyFalse(Literal Lit) const {
655     return static_cast<int8_t>(VarAssignments[var(Lit)]) ==
656            static_cast<int8_t>(Lit & 1);
657   }
658 
659   /// Returns true if and only if `Lit` is watched by a clause in `Formula`.
660   bool isWatched(Literal Lit) const {
661     return Formula.WatchedHead[Lit] != NullClause;
662   }
663 
664   /// Returns an assignment for an unassigned variable.
665   Assignment decideAssignment(Variable Var) const {
666     return !isWatched(posLit(Var)) || isWatched(negLit(Var))
667                ? Assignment::AssignedFalse
668                : Assignment::AssignedTrue;
669   }
670 
671   /// Returns a set of all watched literals.
672   llvm::DenseSet<Literal> watchedLiterals() const {
673     llvm::DenseSet<Literal> WatchedLiterals;
674     for (Literal Lit = 2; Lit < Formula.WatchedHead.size(); Lit++) {
675       if (Formula.WatchedHead[Lit] == NullClause)
676         continue;
677       WatchedLiterals.insert(Lit);
678     }
679     return WatchedLiterals;
680   }
681 
682   /// Returns true if and only if all active variables are unassigned.
683   bool activeVarsAreUnassigned() const {
684     return llvm::all_of(ActiveVars, [this](Variable Var) {
685       return VarAssignments[Var] == Assignment::Unassigned;
686     });
687   }
688 
689   /// Returns true if and only if all active variables form watched literals.
690   bool activeVarsFormWatchedLiterals() const {
691     const llvm::DenseSet<Literal> WatchedLiterals = watchedLiterals();
692     return llvm::all_of(ActiveVars, [&WatchedLiterals](Variable Var) {
693       return WatchedLiterals.contains(posLit(Var)) ||
694              WatchedLiterals.contains(negLit(Var));
695     });
696   }
697 
698   /// Returns true if and only if all unassigned variables that are forming
699   /// watched literals are active.
700   bool unassignedVarsFormingWatchedLiteralsAreActive() const {
701     const llvm::DenseSet<Variable> ActiveVarsSet(ActiveVars.begin(),
702                                                  ActiveVars.end());
703     for (Literal Lit : watchedLiterals()) {
704       const Variable Var = var(Lit);
705       if (VarAssignments[Var] != Assignment::Unassigned)
706         continue;
707       if (ActiveVarsSet.contains(Var))
708         continue;
709       return false;
710     }
711     return true;
712   }
713 };
714 
715 Solver::Result WatchedLiteralsSolver::solve(llvm::DenseSet<BoolValue *> Vals) {
716   return Vals.empty() ? Solver::Result::Satisfiable({{}})
717                       : WatchedLiteralsSolverImpl(Vals).solve();
718 }
719 
720 } // namespace dataflow
721 } // namespace clang
722