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