[DFAJumpThreading] Remove incoming StartBlock from all phis when unfolding select...
[llvm-project.git] / clang / lib / Analysis / FlowSensitive / WatchedLiteralsSolver.cpp
blob3ef3637535324606646a2b3c2ecbf99b3c3ecc62
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.
12 //===----------------------------------------------------------------------===//
14 #include <cassert>
15 #include <cstddef>
16 #include <cstdint>
17 #include <queue>
18 #include <vector>
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/SmallVector.h"
27 #include "llvm/ADT/STLExtras.h"
30 namespace clang {
31 namespace dataflow {
33 // `WatchedLiteralsSolver` is an implementation of Algorithm D from Knuth's
34 // The Art of Computer Programming Volume 4: Satisfiability, Fascicle 6. It is
35 // based on the backtracking DPLL algorithm [1], keeps references to a single
36 // "watched" literal per clause, and uses a set of "active" variables to perform
37 // unit propagation.
39 // The solver expects that its input is a boolean formula in conjunctive normal
40 // form that consists of clauses of at least one literal. A literal is either a
41 // boolean variable or its negation. Below we define types, data structures, and
42 // utilities that are used to represent boolean formulas in conjunctive normal
43 // form.
45 // [1] https://en.wikipedia.org/wiki/DPLL_algorithm
47 /// Boolean variables are represented as positive integers.
48 using Variable = uint32_t;
50 /// A null boolean variable is used as a placeholder in various data structures
51 /// and algorithms.
52 static constexpr Variable NullVar = 0;
54 /// Literals are represented as positive integers. Specifically, for a boolean
55 /// variable `V` that is represented as the positive integer `I`, the positive
56 /// literal `V` is represented as the integer `2*I` and the negative literal
57 /// `!V` is represented as the integer `2*I+1`.
58 using Literal = uint32_t;
60 /// A null literal is used as a placeholder in various data structures and
61 /// algorithms.
62 [[maybe_unused]] static constexpr Literal NullLit = 0;
64 /// Returns the positive literal `V`.
65 static constexpr Literal posLit(Variable V) { return 2 * V; }
67 static constexpr bool isPosLit(Literal L) { return 0 == (L & 1); }
69 static constexpr bool isNegLit(Literal L) { return 1 == (L & 1); }
71 /// Returns the negative literal `!V`.
72 static constexpr Literal negLit(Variable V) { return 2 * V + 1; }
74 /// Returns the negated literal `!L`.
75 static constexpr Literal notLit(Literal L) { return L ^ 1; }
77 /// Returns the variable of `L`.
78 static constexpr Variable var(Literal L) { return L >> 1; }
80 /// Clause identifiers are represented as positive integers.
81 using ClauseID = uint32_t;
83 /// A null clause identifier is used as a placeholder in various data structures
84 /// and algorithms.
85 static constexpr ClauseID NullClause = 0;
87 /// A boolean formula in conjunctive normal form.
88 struct CNFFormula {
89 /// `LargestVar` is equal to the largest positive integer that represents a
90 /// variable in the formula.
91 const Variable LargestVar;
93 /// Literals of all clauses in the formula.
94 ///
95 /// The element at index 0 stands for the literal in the null clause. It is
96 /// set to 0 and isn't used. Literals of clauses in the formula start from the
97 /// element at index 1.
98 ///
99 /// For example, for the formula `(L1 v L2) ^ (L2 v L3 v L4)` the elements of
100 /// `Clauses` will be `[0, L1, L2, L2, L3, L4]`.
101 std::vector<Literal> Clauses;
103 /// Start indices of clauses of the formula in `Clauses`.
105 /// The element at index 0 stands for the start index of the null clause. It
106 /// is set to 0 and isn't used. Start indices of clauses in the formula start
107 /// from the element at index 1.
109 /// For example, for the formula `(L1 v L2) ^ (L2 v L3 v L4)` the elements of
110 /// `ClauseStarts` will be `[0, 1, 3]`. Note that the literals of the first
111 /// clause always start at index 1. The start index for the literals of the
112 /// second clause depends on the size of the first clause and so on.
113 std::vector<size_t> ClauseStarts;
115 /// Maps literals (indices of the vector) to clause identifiers (elements of
116 /// the vector) that watch the respective literals.
118 /// For a given clause, its watched literal is always its first literal in
119 /// `Clauses`. This invariant is maintained when watched literals change.
120 std::vector<ClauseID> WatchedHead;
122 /// Maps clause identifiers (elements of the vector) to identifiers of other
123 /// clauses that watch the same literals, forming a set of linked lists.
125 /// The element at index 0 stands for the identifier of the clause that
126 /// follows the null clause. It is set to 0 and isn't used. Identifiers of
127 /// clauses in the formula start from the element at index 1.
128 std::vector<ClauseID> NextWatched;
130 /// Stores the variable identifier and Atom for atomic booleans in the
131 /// formula.
132 llvm::DenseMap<Variable, Atom> Atomics;
134 /// Indicates that we already know the formula is unsatisfiable.
135 /// During construction, we catch simple cases of conflicting unit-clauses.
136 bool KnownContradictory;
138 explicit CNFFormula(Variable LargestVar,
139 llvm::DenseMap<Variable, Atom> Atomics)
140 : LargestVar(LargestVar), Atomics(std::move(Atomics)),
141 KnownContradictory(false) {
142 Clauses.push_back(0);
143 ClauseStarts.push_back(0);
144 NextWatched.push_back(0);
145 const size_t NumLiterals = 2 * LargestVar + 1;
146 WatchedHead.resize(NumLiterals + 1, 0);
149 /// Adds the `L1 v ... v Ln` clause to the formula.
150 /// Requirements:
152 /// `Li` must not be `NullLit`.
154 /// All literals in the input that are not `NullLit` must be distinct.
155 void addClause(ArrayRef<Literal> lits) {
156 assert(!lits.empty());
157 assert(llvm::all_of(lits, [](Literal L) { return L != NullLit; }));
159 const ClauseID C = ClauseStarts.size();
160 const size_t S = Clauses.size();
161 ClauseStarts.push_back(S);
162 Clauses.insert(Clauses.end(), lits.begin(), lits.end());
164 // Designate the first literal as the "watched" literal of the clause.
165 NextWatched.push_back(WatchedHead[lits.front()]);
166 WatchedHead[lits.front()] = C;
169 /// Returns the number of literals in clause `C`.
170 size_t clauseSize(ClauseID C) const {
171 return C == ClauseStarts.size() - 1 ? Clauses.size() - ClauseStarts[C]
172 : ClauseStarts[C + 1] - ClauseStarts[C];
175 /// Returns the literals of clause `C`.
176 llvm::ArrayRef<Literal> clauseLiterals(ClauseID C) const {
177 return llvm::ArrayRef<Literal>(&Clauses[ClauseStarts[C]], clauseSize(C));
181 /// Applies simplifications while building up a BooleanFormula.
182 /// We keep track of unit clauses, which tell us variables that must be
183 /// true/false in any model that satisfies the overall formula.
184 /// Such variables can be dropped from subsequently-added clauses, which
185 /// may in turn yield more unit clauses or even a contradiction.
186 /// The total added complexity of this preprocessing is O(N) where we
187 /// for every clause, we do a lookup for each unit clauses.
188 /// The lookup is O(1) on average. This method won't catch all
189 /// contradictory formulas, more passes can in principle catch
190 /// more cases but we leave all these and the general case to the
191 /// proper SAT solver.
192 struct CNFFormulaBuilder {
193 // Formula should outlive CNFFormulaBuilder.
194 explicit CNFFormulaBuilder(CNFFormula &CNF)
195 : Formula(CNF) {}
197 /// Adds the `L1 v ... v Ln` clause to the formula. Applies
198 /// simplifications, based on single-literal clauses.
200 /// Requirements:
202 /// `Li` must not be `NullLit`.
204 /// All literals must be distinct.
205 void addClause(ArrayRef<Literal> Literals) {
206 // We generate clauses with up to 3 literals in this file.
207 assert(!Literals.empty() && Literals.size() <= 3);
208 // Contains literals of the simplified clause.
209 llvm::SmallVector<Literal> Simplified;
210 for (auto L : Literals) {
211 assert(L != NullLit &&
212 llvm::all_of(Simplified,
213 [L](Literal S) { return S != L; }));
214 auto X = var(L);
215 if (trueVars.contains(X)) { // X must be true
216 if (isPosLit(L))
217 return; // Omit clause `(... v X v ...)`, it is `true`.
218 else
219 continue; // Omit `!X` from `(... v !X v ...)`.
221 if (falseVars.contains(X)) { // X must be false
222 if (isNegLit(L))
223 return; // Omit clause `(... v !X v ...)`, it is `true`.
224 else
225 continue; // Omit `X` from `(... v X v ...)`.
227 Simplified.push_back(L);
229 if (Simplified.empty()) {
230 // Simplification made the clause empty, which is equivalent to `false`.
231 // We already know that this formula is unsatisfiable.
232 Formula.KnownContradictory = true;
233 // We can add any of the input literals to get an unsatisfiable formula.
234 Formula.addClause(Literals[0]);
235 return;
237 if (Simplified.size() == 1) {
238 // We have new unit clause.
239 const Literal lit = Simplified.front();
240 const Variable v = var(lit);
241 if (isPosLit(lit))
242 trueVars.insert(v);
243 else
244 falseVars.insert(v);
246 Formula.addClause(Simplified);
249 /// Returns true if we observed a contradiction while adding clauses.
250 /// In this case then the formula is already known to be unsatisfiable.
251 bool isKnownContradictory() { return Formula.KnownContradictory; }
253 private:
254 CNFFormula &Formula;
255 llvm::DenseSet<Variable> trueVars;
256 llvm::DenseSet<Variable> falseVars;
259 /// Converts the conjunction of `Vals` into a formula in conjunctive normal
260 /// form where each clause has at least one and at most three literals.
261 CNFFormula buildCNF(const llvm::ArrayRef<const Formula *> &Vals) {
262 // The general strategy of the algorithm implemented below is to map each
263 // of the sub-values in `Vals` to a unique variable and use these variables in
264 // the resulting CNF expression to avoid exponential blow up. The number of
265 // literals in the resulting formula is guaranteed to be linear in the number
266 // of sub-formulas in `Vals`.
268 // Map each sub-formula in `Vals` to a unique variable.
269 llvm::DenseMap<const Formula *, Variable> SubValsToVar;
270 // Store variable identifiers and Atom of atomic booleans.
271 llvm::DenseMap<Variable, Atom> Atomics;
272 Variable NextVar = 1;
274 std::queue<const Formula *> UnprocessedSubVals;
275 for (const Formula *Val : Vals)
276 UnprocessedSubVals.push(Val);
277 while (!UnprocessedSubVals.empty()) {
278 Variable Var = NextVar;
279 const Formula *Val = UnprocessedSubVals.front();
280 UnprocessedSubVals.pop();
282 if (!SubValsToVar.try_emplace(Val, Var).second)
283 continue;
284 ++NextVar;
286 for (const Formula *F : Val->operands())
287 UnprocessedSubVals.push(F);
288 if (Val->kind() == Formula::AtomRef)
289 Atomics[Var] = Val->getAtom();
293 auto GetVar = [&SubValsToVar](const Formula *Val) {
294 auto ValIt = SubValsToVar.find(Val);
295 assert(ValIt != SubValsToVar.end());
296 return ValIt->second;
299 CNFFormula CNF(NextVar - 1, std::move(Atomics));
300 std::vector<bool> ProcessedSubVals(NextVar, false);
301 CNFFormulaBuilder builder(CNF);
303 // Add a conjunct for each variable that represents a top-level conjunction
304 // value in `Vals`.
305 for (const Formula *Val : Vals)
306 builder.addClause(posLit(GetVar(Val)));
308 // Add conjuncts that represent the mapping between newly-created variables
309 // and their corresponding sub-formulas.
310 std::queue<const Formula *> UnprocessedSubVals;
311 for (const Formula *Val : Vals)
312 UnprocessedSubVals.push(Val);
313 while (!UnprocessedSubVals.empty()) {
314 const Formula *Val = UnprocessedSubVals.front();
315 UnprocessedSubVals.pop();
316 const Variable Var = GetVar(Val);
318 if (ProcessedSubVals[Var])
319 continue;
320 ProcessedSubVals[Var] = true;
322 switch (Val->kind()) {
323 case Formula::AtomRef:
324 break;
325 case Formula::Literal:
326 CNF.addClause(Val->literal() ? posLit(Var) : negLit(Var));
327 break;
328 case Formula::And: {
329 const Variable LHS = GetVar(Val->operands()[0]);
330 const Variable RHS = GetVar(Val->operands()[1]);
332 if (LHS == RHS) {
333 // `X <=> (A ^ A)` is equivalent to `(!X v A) ^ (X v !A)` which is
334 // already in conjunctive normal form. Below we add each of the
335 // conjuncts of the latter expression to the result.
336 builder.addClause({negLit(Var), posLit(LHS)});
337 builder.addClause({posLit(Var), negLit(LHS)});
338 } else {
339 // `X <=> (A ^ B)` is equivalent to `(!X v A) ^ (!X v B) ^ (X v !A v
340 // !B)` which is already in conjunctive normal form. Below we add each
341 // of the conjuncts of the latter expression to the result.
342 builder.addClause({negLit(Var), posLit(LHS)});
343 builder.addClause({negLit(Var), posLit(RHS)});
344 builder.addClause({posLit(Var), negLit(LHS), negLit(RHS)});
346 break;
348 case Formula::Or: {
349 const Variable LHS = GetVar(Val->operands()[0]);
350 const Variable RHS = GetVar(Val->operands()[1]);
352 if (LHS == RHS) {
353 // `X <=> (A v A)` is equivalent to `(!X v A) ^ (X v !A)` which is
354 // already in conjunctive normal form. Below we add each of the
355 // conjuncts of the latter expression to the result.
356 builder.addClause({negLit(Var), posLit(LHS)});
357 builder.addClause({posLit(Var), negLit(LHS)});
358 } else {
359 // `X <=> (A v B)` is equivalent to `(!X v A v B) ^ (X v !A) ^ (X v
360 // !B)` which is already in conjunctive normal form. Below we add each
361 // of the conjuncts of the latter expression to the result.
362 builder.addClause({negLit(Var), posLit(LHS), posLit(RHS)});
363 builder.addClause({posLit(Var), negLit(LHS)});
364 builder.addClause({posLit(Var), negLit(RHS)});
366 break;
368 case Formula::Not: {
369 const Variable Operand = GetVar(Val->operands()[0]);
371 // `X <=> !Y` is equivalent to `(!X v !Y) ^ (X v Y)` which is
372 // already in conjunctive normal form. Below we add each of the
373 // conjuncts of the latter expression to the result.
374 builder.addClause({negLit(Var), negLit(Operand)});
375 builder.addClause({posLit(Var), posLit(Operand)});
376 break;
378 case Formula::Implies: {
379 const Variable LHS = GetVar(Val->operands()[0]);
380 const Variable RHS = GetVar(Val->operands()[1]);
382 // `X <=> (A => B)` is equivalent to
383 // `(X v A) ^ (X v !B) ^ (!X v !A v B)` which is already in
384 // conjunctive normal form. Below we add each of the conjuncts of
385 // the latter expression to the result.
386 builder.addClause({posLit(Var), posLit(LHS)});
387 builder.addClause({posLit(Var), negLit(RHS)});
388 builder.addClause({negLit(Var), negLit(LHS), posLit(RHS)});
389 break;
391 case Formula::Equal: {
392 const Variable LHS = GetVar(Val->operands()[0]);
393 const Variable RHS = GetVar(Val->operands()[1]);
395 if (LHS == RHS) {
396 // `X <=> (A <=> A)` is equivalent to `X` which is already in
397 // conjunctive normal form. Below we add each of the conjuncts of the
398 // latter expression to the result.
399 builder.addClause(posLit(Var));
401 // No need to visit the sub-values of `Val`.
402 continue;
404 // `X <=> (A <=> B)` is equivalent to
405 // `(X v A v B) ^ (X v !A v !B) ^ (!X v A v !B) ^ (!X v !A v B)` which
406 // is already in conjunctive normal form. Below we add each of the
407 // conjuncts of the latter expression to the result.
408 builder.addClause({posLit(Var), posLit(LHS), posLit(RHS)});
409 builder.addClause({posLit(Var), negLit(LHS), negLit(RHS)});
410 builder.addClause({negLit(Var), posLit(LHS), negLit(RHS)});
411 builder.addClause({negLit(Var), negLit(LHS), posLit(RHS)});
412 break;
415 if (builder.isKnownContradictory()) {
416 return CNF;
418 for (const Formula *Child : Val->operands())
419 UnprocessedSubVals.push(Child);
422 // Unit clauses that were added later were not
423 // considered for the simplification of earlier clauses. Do a final
424 // pass to find more opportunities for simplification.
425 CNFFormula FinalCNF(NextVar - 1, std::move(CNF.Atomics));
426 CNFFormulaBuilder FinalBuilder(FinalCNF);
428 // Collect unit clauses.
429 for (ClauseID C = 1; C < CNF.ClauseStarts.size(); ++C) {
430 if (CNF.clauseSize(C) == 1) {
431 FinalBuilder.addClause(CNF.clauseLiterals(C)[0]);
435 // Add all clauses that were added previously, preserving the order.
436 for (ClauseID C = 1; C < CNF.ClauseStarts.size(); ++C) {
437 FinalBuilder.addClause(CNF.clauseLiterals(C));
438 if (FinalBuilder.isKnownContradictory()) {
439 break;
442 // It is possible there were new unit clauses again, but
443 // we stop here and leave the rest to the solver algorithm.
444 return FinalCNF;
447 class WatchedLiteralsSolverImpl {
448 /// A boolean formula in conjunctive normal form that the solver will attempt
449 /// to prove satisfiable. The formula will be modified in the process.
450 CNFFormula CNF;
452 /// The search for a satisfying assignment of the variables in `Formula` will
453 /// proceed in levels, starting from 1 and going up to `Formula.LargestVar`
454 /// (inclusive). The current level is stored in `Level`. At each level the
455 /// solver will assign a value to an unassigned variable. If this leads to a
456 /// consistent partial assignment, `Level` will be incremented. Otherwise, if
457 /// it results in a conflict, the solver will backtrack by decrementing
458 /// `Level` until it reaches the most recent level where a decision was made.
459 size_t Level = 0;
461 /// Maps levels (indices of the vector) to variables (elements of the vector)
462 /// that are assigned values at the respective levels.
464 /// The element at index 0 isn't used. Variables start from the element at
465 /// index 1.
466 std::vector<Variable> LevelVars;
468 /// State of the solver at a particular level.
469 enum class State : uint8_t {
470 /// Indicates that the solver made a decision.
471 Decision = 0,
473 /// Indicates that the solver made a forced move.
474 Forced = 1,
477 /// State of the solver at a particular level. It keeps track of previous
478 /// decisions that the solver can refer to when backtracking.
480 /// The element at index 0 isn't used. States start from the element at index
481 /// 1.
482 std::vector<State> LevelStates;
484 enum class Assignment : int8_t {
485 Unassigned = -1,
486 AssignedFalse = 0,
487 AssignedTrue = 1
490 /// Maps variables (indices of the vector) to their assignments (elements of
491 /// the vector).
493 /// The element at index 0 isn't used. Variable assignments start from the
494 /// element at index 1.
495 std::vector<Assignment> VarAssignments;
497 /// A set of unassigned variables that appear in watched literals in
498 /// `Formula`. The vector is guaranteed to contain unique elements.
499 std::vector<Variable> ActiveVars;
501 public:
502 explicit WatchedLiteralsSolverImpl(
503 const llvm::ArrayRef<const Formula *> &Vals)
504 : CNF(buildCNF(Vals)), LevelVars(CNF.LargestVar + 1),
505 LevelStates(CNF.LargestVar + 1) {
506 assert(!Vals.empty());
508 // Initialize the state at the root level to a decision so that in
509 // `reverseForcedMoves` we don't have to check that `Level >= 0` on each
510 // iteration.
511 LevelStates[0] = State::Decision;
513 // Initialize all variables as unassigned.
514 VarAssignments.resize(CNF.LargestVar + 1, Assignment::Unassigned);
516 // Initialize the active variables.
517 for (Variable Var = CNF.LargestVar; Var != NullVar; --Var) {
518 if (isWatched(posLit(Var)) || isWatched(negLit(Var)))
519 ActiveVars.push_back(Var);
523 // Returns the `Result` and the number of iterations "remaining" from
524 // `MaxIterations` (that is, `MaxIterations` - iterations in this call).
525 std::pair<Solver::Result, std::int64_t> solve(std::int64_t MaxIterations) && {
526 if (CNF.KnownContradictory) {
527 // Short-cut the solving process. We already found out at CNF
528 // construction time that the formula is unsatisfiable.
529 return std::make_pair(Solver::Result::Unsatisfiable(), MaxIterations);
531 size_t I = 0;
532 while (I < ActiveVars.size()) {
533 if (MaxIterations == 0)
534 return std::make_pair(Solver::Result::TimedOut(), 0);
535 --MaxIterations;
537 // Assert that the following invariants hold:
538 // 1. All active variables are unassigned.
539 // 2. All active variables form watched literals.
540 // 3. Unassigned variables that form watched literals are active.
541 // FIXME: Consider replacing these with test cases that fail if the any
542 // of the invariants is broken. That might not be easy due to the
543 // transformations performed by `buildCNF`.
544 assert(activeVarsAreUnassigned());
545 assert(activeVarsFormWatchedLiterals());
546 assert(unassignedVarsFormingWatchedLiteralsAreActive());
548 const Variable ActiveVar = ActiveVars[I];
550 // Look for unit clauses that contain the active variable.
551 const bool unitPosLit = watchedByUnitClause(posLit(ActiveVar));
552 const bool unitNegLit = watchedByUnitClause(negLit(ActiveVar));
553 if (unitPosLit && unitNegLit) {
554 // We found a conflict!
556 // Backtrack and rewind the `Level` until the most recent non-forced
557 // assignment.
558 reverseForcedMoves();
560 // If the root level is reached, then all possible assignments lead to
561 // a conflict.
562 if (Level == 0)
563 return std::make_pair(Solver::Result::Unsatisfiable(), MaxIterations);
565 // Otherwise, take the other branch at the most recent level where a
566 // decision was made.
567 LevelStates[Level] = State::Forced;
568 const Variable Var = LevelVars[Level];
569 VarAssignments[Var] = VarAssignments[Var] == Assignment::AssignedTrue
570 ? Assignment::AssignedFalse
571 : Assignment::AssignedTrue;
573 updateWatchedLiterals();
574 } else if (unitPosLit || unitNegLit) {
575 // We found a unit clause! The value of its unassigned variable is
576 // forced.
577 ++Level;
579 LevelVars[Level] = ActiveVar;
580 LevelStates[Level] = State::Forced;
581 VarAssignments[ActiveVar] =
582 unitPosLit ? Assignment::AssignedTrue : Assignment::AssignedFalse;
584 // Remove the variable that was just assigned from the set of active
585 // variables.
586 if (I + 1 < ActiveVars.size()) {
587 // Replace the variable that was just assigned with the last active
588 // variable for efficient removal.
589 ActiveVars[I] = ActiveVars.back();
590 } else {
591 // This was the last active variable. Repeat the process from the
592 // beginning.
593 I = 0;
595 ActiveVars.pop_back();
597 updateWatchedLiterals();
598 } else if (I + 1 == ActiveVars.size()) {
599 // There are no remaining unit clauses in the formula! Make a decision
600 // for one of the active variables at the current level.
601 ++Level;
603 LevelVars[Level] = ActiveVar;
604 LevelStates[Level] = State::Decision;
605 VarAssignments[ActiveVar] = decideAssignment(ActiveVar);
607 // Remove the variable that was just assigned from the set of active
608 // variables.
609 ActiveVars.pop_back();
611 updateWatchedLiterals();
613 // This was the last active variable. Repeat the process from the
614 // beginning.
615 I = 0;
616 } else {
617 ++I;
620 return std::make_pair(Solver::Result::Satisfiable(buildSolution()),
621 MaxIterations);
624 private:
625 /// Returns a satisfying truth assignment to the atoms in the boolean formula.
626 llvm::DenseMap<Atom, Solver::Result::Assignment> buildSolution() {
627 llvm::DenseMap<Atom, Solver::Result::Assignment> Solution;
628 for (auto &Atomic : CNF.Atomics) {
629 // A variable may have a definite true/false assignment, or it may be
630 // unassigned indicating its truth value does not affect the result of
631 // the formula. Unassigned variables are assigned to true as a default.
632 Solution[Atomic.second] =
633 VarAssignments[Atomic.first] == Assignment::AssignedFalse
634 ? Solver::Result::Assignment::AssignedFalse
635 : Solver::Result::Assignment::AssignedTrue;
637 return Solution;
640 /// Reverses forced moves until the most recent level where a decision was
641 /// made on the assignment of a variable.
642 void reverseForcedMoves() {
643 for (; LevelStates[Level] == State::Forced; --Level) {
644 const Variable Var = LevelVars[Level];
646 VarAssignments[Var] = Assignment::Unassigned;
648 // If the variable that we pass through is watched then we add it to the
649 // active variables.
650 if (isWatched(posLit(Var)) || isWatched(negLit(Var)))
651 ActiveVars.push_back(Var);
655 /// Updates watched literals that are affected by a variable assignment.
656 void updateWatchedLiterals() {
657 const Variable Var = LevelVars[Level];
659 // Update the watched literals of clauses that currently watch the literal
660 // that falsifies `Var`.
661 const Literal FalseLit = VarAssignments[Var] == Assignment::AssignedTrue
662 ? negLit(Var)
663 : posLit(Var);
664 ClauseID FalseLitWatcher = CNF.WatchedHead[FalseLit];
665 CNF.WatchedHead[FalseLit] = NullClause;
666 while (FalseLitWatcher != NullClause) {
667 const ClauseID NextFalseLitWatcher = CNF.NextWatched[FalseLitWatcher];
669 // Pick the first non-false literal as the new watched literal.
670 const size_t FalseLitWatcherStart = CNF.ClauseStarts[FalseLitWatcher];
671 size_t NewWatchedLitIdx = FalseLitWatcherStart + 1;
672 while (isCurrentlyFalse(CNF.Clauses[NewWatchedLitIdx]))
673 ++NewWatchedLitIdx;
674 const Literal NewWatchedLit = CNF.Clauses[NewWatchedLitIdx];
675 const Variable NewWatchedLitVar = var(NewWatchedLit);
677 // Swap the old watched literal for the new one in `FalseLitWatcher` to
678 // maintain the invariant that the watched literal is at the beginning of
679 // the clause.
680 CNF.Clauses[NewWatchedLitIdx] = FalseLit;
681 CNF.Clauses[FalseLitWatcherStart] = NewWatchedLit;
683 // If the new watched literal isn't watched by any other clause and its
684 // variable isn't assigned we need to add it to the active variables.
685 if (!isWatched(NewWatchedLit) && !isWatched(notLit(NewWatchedLit)) &&
686 VarAssignments[NewWatchedLitVar] == Assignment::Unassigned)
687 ActiveVars.push_back(NewWatchedLitVar);
689 CNF.NextWatched[FalseLitWatcher] = CNF.WatchedHead[NewWatchedLit];
690 CNF.WatchedHead[NewWatchedLit] = FalseLitWatcher;
692 // Go to the next clause that watches `FalseLit`.
693 FalseLitWatcher = NextFalseLitWatcher;
697 /// Returns true if and only if one of the clauses that watch `Lit` is a unit
698 /// clause.
699 bool watchedByUnitClause(Literal Lit) const {
700 for (ClauseID LitWatcher = CNF.WatchedHead[Lit]; LitWatcher != NullClause;
701 LitWatcher = CNF.NextWatched[LitWatcher]) {
702 llvm::ArrayRef<Literal> Clause = CNF.clauseLiterals(LitWatcher);
704 // Assert the invariant that the watched literal is always the first one
705 // in the clause.
706 // FIXME: Consider replacing this with a test case that fails if the
707 // invariant is broken by `updateWatchedLiterals`. That might not be easy
708 // due to the transformations performed by `buildCNF`.
709 assert(Clause.front() == Lit);
711 if (isUnit(Clause))
712 return true;
714 return false;
717 /// Returns true if and only if `Clause` is a unit clause.
718 bool isUnit(llvm::ArrayRef<Literal> Clause) const {
719 return llvm::all_of(Clause.drop_front(),
720 [this](Literal L) { return isCurrentlyFalse(L); });
723 /// Returns true if and only if `Lit` evaluates to `false` in the current
724 /// partial assignment.
725 bool isCurrentlyFalse(Literal Lit) const {
726 return static_cast<int8_t>(VarAssignments[var(Lit)]) ==
727 static_cast<int8_t>(Lit & 1);
730 /// Returns true if and only if `Lit` is watched by a clause in `Formula`.
731 bool isWatched(Literal Lit) const {
732 return CNF.WatchedHead[Lit] != NullClause;
735 /// Returns an assignment for an unassigned variable.
736 Assignment decideAssignment(Variable Var) const {
737 return !isWatched(posLit(Var)) || isWatched(negLit(Var))
738 ? Assignment::AssignedFalse
739 : Assignment::AssignedTrue;
742 /// Returns a set of all watched literals.
743 llvm::DenseSet<Literal> watchedLiterals() const {
744 llvm::DenseSet<Literal> WatchedLiterals;
745 for (Literal Lit = 2; Lit < CNF.WatchedHead.size(); Lit++) {
746 if (CNF.WatchedHead[Lit] == NullClause)
747 continue;
748 WatchedLiterals.insert(Lit);
750 return WatchedLiterals;
753 /// Returns true if and only if all active variables are unassigned.
754 bool activeVarsAreUnassigned() const {
755 return llvm::all_of(ActiveVars, [this](Variable Var) {
756 return VarAssignments[Var] == Assignment::Unassigned;
760 /// Returns true if and only if all active variables form watched literals.
761 bool activeVarsFormWatchedLiterals() const {
762 const llvm::DenseSet<Literal> WatchedLiterals = watchedLiterals();
763 return llvm::all_of(ActiveVars, [&WatchedLiterals](Variable Var) {
764 return WatchedLiterals.contains(posLit(Var)) ||
765 WatchedLiterals.contains(negLit(Var));
769 /// Returns true if and only if all unassigned variables that are forming
770 /// watched literals are active.
771 bool unassignedVarsFormingWatchedLiteralsAreActive() const {
772 const llvm::DenseSet<Variable> ActiveVarsSet(ActiveVars.begin(),
773 ActiveVars.end());
774 for (Literal Lit : watchedLiterals()) {
775 const Variable Var = var(Lit);
776 if (VarAssignments[Var] != Assignment::Unassigned)
777 continue;
778 if (ActiveVarsSet.contains(Var))
779 continue;
780 return false;
782 return true;
786 Solver::Result
787 WatchedLiteralsSolver::solve(llvm::ArrayRef<const Formula *> Vals) {
788 if (Vals.empty())
789 return Solver::Result::Satisfiable({{}});
790 auto [Res, Iterations] = WatchedLiteralsSolverImpl(Vals).solve(MaxIterations);
791 MaxIterations = Iterations;
792 return Res;
795 } // namespace dataflow
796 } // namespace clang