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