1ae60884dSStanislav Gatev //===- unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp ---===//
2ae60884dSStanislav Gatev //
3ae60884dSStanislav Gatev // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ae60884dSStanislav Gatev // See https://llvm.org/LICENSE.txt for license information.
5ae60884dSStanislav Gatev // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ae60884dSStanislav Gatev //
7ae60884dSStanislav Gatev //===----------------------------------------------------------------------===//
8ae60884dSStanislav Gatev 
9ae60884dSStanislav Gatev #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
10ae60884dSStanislav Gatev #include "clang/Analysis/FlowSensitive/WatchedLiteralsSolver.h"
11ae60884dSStanislav Gatev #include "gmock/gmock.h"
12ae60884dSStanislav Gatev #include "gtest/gtest.h"
13ae60884dSStanislav Gatev #include <memory>
14ae60884dSStanislav Gatev 
15ae60884dSStanislav Gatev namespace {
16ae60884dSStanislav Gatev 
17ae60884dSStanislav Gatev using namespace clang;
18ae60884dSStanislav Gatev using namespace dataflow;
19ae60884dSStanislav Gatev 
20ae60884dSStanislav Gatev class DataflowAnalysisContextTest : public ::testing::Test {
21ae60884dSStanislav Gatev protected:
22ae60884dSStanislav Gatev   DataflowAnalysisContextTest()
23ae60884dSStanislav Gatev       : Context(std::make_unique<WatchedLiteralsSolver>()) {}
24ae60884dSStanislav Gatev 
25ae60884dSStanislav Gatev   DataflowAnalysisContext Context;
26ae60884dSStanislav Gatev };
27ae60884dSStanislav Gatev 
28ae60884dSStanislav Gatev TEST_F(DataflowAnalysisContextTest,
29ae60884dSStanislav Gatev        CreateAtomicBoolValueReturnsDistinctValues) {
30ae60884dSStanislav Gatev   auto &X = Context.createAtomicBoolValue();
31ae60884dSStanislav Gatev   auto &Y = Context.createAtomicBoolValue();
32ae60884dSStanislav Gatev   EXPECT_NE(&X, &Y);
33ae60884dSStanislav Gatev }
34ae60884dSStanislav Gatev 
35ae60884dSStanislav Gatev TEST_F(DataflowAnalysisContextTest,
3600e9d534SWei Yi Tee        GetOrCreateConjunctionReturnsSameExprGivenSameArgs) {
37ae60884dSStanislav Gatev   auto &X = Context.createAtomicBoolValue();
3800e9d534SWei Yi Tee   auto &XAndX = Context.getOrCreateConjunction(X, X);
39ae60884dSStanislav Gatev   EXPECT_EQ(&XAndX, &X);
40ae60884dSStanislav Gatev }
41ae60884dSStanislav Gatev 
42ae60884dSStanislav Gatev TEST_F(DataflowAnalysisContextTest,
4300e9d534SWei Yi Tee        GetOrCreateConjunctionReturnsSameExprOnSubsequentCalls) {
44ae60884dSStanislav Gatev   auto &X = Context.createAtomicBoolValue();
45ae60884dSStanislav Gatev   auto &Y = Context.createAtomicBoolValue();
4600e9d534SWei Yi Tee   auto &XAndY1 = Context.getOrCreateConjunction(X, Y);
4700e9d534SWei Yi Tee   auto &XAndY2 = Context.getOrCreateConjunction(X, Y);
48ae60884dSStanislav Gatev   EXPECT_EQ(&XAndY1, &XAndY2);
49ae60884dSStanislav Gatev 
5000e9d534SWei Yi Tee   auto &YAndX = Context.getOrCreateConjunction(Y, X);
51ae60884dSStanislav Gatev   EXPECT_EQ(&XAndY1, &YAndX);
52ae60884dSStanislav Gatev 
53ae60884dSStanislav Gatev   auto &Z = Context.createAtomicBoolValue();
5400e9d534SWei Yi Tee   auto &XAndZ = Context.getOrCreateConjunction(X, Z);
55ae60884dSStanislav Gatev   EXPECT_NE(&XAndY1, &XAndZ);
56ae60884dSStanislav Gatev }
57ae60884dSStanislav Gatev 
58ae60884dSStanislav Gatev TEST_F(DataflowAnalysisContextTest,
5900e9d534SWei Yi Tee        GetOrCreateDisjunctionReturnsSameExprGivenSameArgs) {
60ae60884dSStanislav Gatev   auto &X = Context.createAtomicBoolValue();
6100e9d534SWei Yi Tee   auto &XOrX = Context.getOrCreateDisjunction(X, X);
62ae60884dSStanislav Gatev   EXPECT_EQ(&XOrX, &X);
63ae60884dSStanislav Gatev }
64ae60884dSStanislav Gatev 
65ae60884dSStanislav Gatev TEST_F(DataflowAnalysisContextTest,
6600e9d534SWei Yi Tee        GetOrCreateDisjunctionReturnsSameExprOnSubsequentCalls) {
67ae60884dSStanislav Gatev   auto &X = Context.createAtomicBoolValue();
68ae60884dSStanislav Gatev   auto &Y = Context.createAtomicBoolValue();
6900e9d534SWei Yi Tee   auto &XOrY1 = Context.getOrCreateDisjunction(X, Y);
7000e9d534SWei Yi Tee   auto &XOrY2 = Context.getOrCreateDisjunction(X, Y);
71ae60884dSStanislav Gatev   EXPECT_EQ(&XOrY1, &XOrY2);
72ae60884dSStanislav Gatev 
7300e9d534SWei Yi Tee   auto &YOrX = Context.getOrCreateDisjunction(Y, X);
74ae60884dSStanislav Gatev   EXPECT_EQ(&XOrY1, &YOrX);
75ae60884dSStanislav Gatev 
76ae60884dSStanislav Gatev   auto &Z = Context.createAtomicBoolValue();
7700e9d534SWei Yi Tee   auto &XOrZ = Context.getOrCreateDisjunction(X, Z);
78ae60884dSStanislav Gatev   EXPECT_NE(&XOrY1, &XOrZ);
79ae60884dSStanislav Gatev }
80ae60884dSStanislav Gatev 
81ae60884dSStanislav Gatev TEST_F(DataflowAnalysisContextTest,
8200e9d534SWei Yi Tee        GetOrCreateNegationReturnsSameExprOnSubsequentCalls) {
83ae60884dSStanislav Gatev   auto &X = Context.createAtomicBoolValue();
8400e9d534SWei Yi Tee   auto &NotX1 = Context.getOrCreateNegation(X);
8500e9d534SWei Yi Tee   auto &NotX2 = Context.getOrCreateNegation(X);
86ae60884dSStanislav Gatev   EXPECT_EQ(&NotX1, &NotX2);
87ae60884dSStanislav Gatev 
88ae60884dSStanislav Gatev   auto &Y = Context.createAtomicBoolValue();
8900e9d534SWei Yi Tee   auto &NotY = Context.getOrCreateNegation(Y);
90ae60884dSStanislav Gatev   EXPECT_NE(&NotX1, &NotY);
91ae60884dSStanislav Gatev }
92ae60884dSStanislav Gatev 
9300e9d534SWei Yi Tee TEST_F(DataflowAnalysisContextTest,
9400e9d534SWei Yi Tee        GetOrCreateImplicationReturnsTrueGivenSameArgs) {
9500e9d534SWei Yi Tee   auto &X = Context.createAtomicBoolValue();
9600e9d534SWei Yi Tee   auto &XImpliesX = Context.getOrCreateImplication(X, X);
9700e9d534SWei Yi Tee   EXPECT_EQ(&XImpliesX, &Context.getBoolLiteralValue(true));
9800e9d534SWei Yi Tee }
9900e9d534SWei Yi Tee 
10000e9d534SWei Yi Tee TEST_F(DataflowAnalysisContextTest,
10100e9d534SWei Yi Tee        GetOrCreateImplicationReturnsSameExprOnSubsequentCalls) {
10200e9d534SWei Yi Tee   auto &X = Context.createAtomicBoolValue();
10300e9d534SWei Yi Tee   auto &Y = Context.createAtomicBoolValue();
10400e9d534SWei Yi Tee   auto &XImpliesY1 = Context.getOrCreateImplication(X, Y);
10500e9d534SWei Yi Tee   auto &XImpliesY2 = Context.getOrCreateImplication(X, Y);
10600e9d534SWei Yi Tee   EXPECT_EQ(&XImpliesY1, &XImpliesY2);
10700e9d534SWei Yi Tee 
10800e9d534SWei Yi Tee   auto &YImpliesX = Context.getOrCreateImplication(Y, X);
10900e9d534SWei Yi Tee   EXPECT_NE(&XImpliesY1, &YImpliesX);
11000e9d534SWei Yi Tee 
11100e9d534SWei Yi Tee   auto &Z = Context.createAtomicBoolValue();
11200e9d534SWei Yi Tee   auto &XImpliesZ = Context.getOrCreateImplication(X, Z);
11300e9d534SWei Yi Tee   EXPECT_NE(&XImpliesY1, &XImpliesZ);
11400e9d534SWei Yi Tee }
11500e9d534SWei Yi Tee 
11600e9d534SWei Yi Tee TEST_F(DataflowAnalysisContextTest, GetOrCreateIffReturnsTrueGivenSameArgs) {
11700e9d534SWei Yi Tee   auto &X = Context.createAtomicBoolValue();
11800e9d534SWei Yi Tee   auto &XIffX = Context.getOrCreateIff(X, X);
11900e9d534SWei Yi Tee   EXPECT_EQ(&XIffX, &Context.getBoolLiteralValue(true));
12000e9d534SWei Yi Tee }
12100e9d534SWei Yi Tee 
12200e9d534SWei Yi Tee TEST_F(DataflowAnalysisContextTest,
12300e9d534SWei Yi Tee        GetOrCreateIffReturnsSameExprOnSubsequentCalls) {
12400e9d534SWei Yi Tee   auto &X = Context.createAtomicBoolValue();
12500e9d534SWei Yi Tee   auto &Y = Context.createAtomicBoolValue();
12600e9d534SWei Yi Tee   auto &XIffY1 = Context.getOrCreateIff(X, Y);
12700e9d534SWei Yi Tee   auto &XIffY2 = Context.getOrCreateIff(X, Y);
12800e9d534SWei Yi Tee   EXPECT_EQ(&XIffY1, &XIffY2);
12900e9d534SWei Yi Tee 
13000e9d534SWei Yi Tee   auto &YIffX = Context.getOrCreateIff(Y, X);
13100e9d534SWei Yi Tee   EXPECT_EQ(&XIffY1, &YIffX);
13200e9d534SWei Yi Tee 
13300e9d534SWei Yi Tee   auto &Z = Context.createAtomicBoolValue();
13400e9d534SWei Yi Tee   auto &XIffZ = Context.getOrCreateIff(X, Z);
13500e9d534SWei Yi Tee   EXPECT_NE(&XIffY1, &XIffZ);
13600e9d534SWei Yi Tee }
13700e9d534SWei Yi Tee 
138955a05a2SStanislav Gatev TEST_F(DataflowAnalysisContextTest, EmptyFlowCondition) {
139955a05a2SStanislav Gatev   auto &FC = Context.makeFlowConditionToken();
140955a05a2SStanislav Gatev   auto &C = Context.createAtomicBoolValue();
141955a05a2SStanislav Gatev   EXPECT_FALSE(Context.flowConditionImplies(FC, C));
142955a05a2SStanislav Gatev }
143955a05a2SStanislav Gatev 
144955a05a2SStanislav Gatev TEST_F(DataflowAnalysisContextTest, AddFlowConditionConstraint) {
145955a05a2SStanislav Gatev   auto &FC = Context.makeFlowConditionToken();
146955a05a2SStanislav Gatev   auto &C = Context.createAtomicBoolValue();
147955a05a2SStanislav Gatev   Context.addFlowConditionConstraint(FC, C);
148955a05a2SStanislav Gatev   EXPECT_TRUE(Context.flowConditionImplies(FC, C));
149955a05a2SStanislav Gatev }
150955a05a2SStanislav Gatev 
151955a05a2SStanislav Gatev TEST_F(DataflowAnalysisContextTest, ForkFlowCondition) {
152955a05a2SStanislav Gatev   auto &FC1 = Context.makeFlowConditionToken();
153955a05a2SStanislav Gatev   auto &C1 = Context.createAtomicBoolValue();
154955a05a2SStanislav Gatev   Context.addFlowConditionConstraint(FC1, C1);
155955a05a2SStanislav Gatev 
156955a05a2SStanislav Gatev   // Forked flow condition inherits the constraints of its parent flow
157955a05a2SStanislav Gatev   // condition.
158955a05a2SStanislav Gatev   auto &FC2 = Context.forkFlowCondition(FC1);
159955a05a2SStanislav Gatev   EXPECT_TRUE(Context.flowConditionImplies(FC2, C1));
160955a05a2SStanislav Gatev 
161955a05a2SStanislav Gatev   // Adding a new constraint to the forked flow condition does not affect its
162955a05a2SStanislav Gatev   // parent flow condition.
163955a05a2SStanislav Gatev   auto &C2 = Context.createAtomicBoolValue();
164955a05a2SStanislav Gatev   Context.addFlowConditionConstraint(FC2, C2);
165955a05a2SStanislav Gatev   EXPECT_TRUE(Context.flowConditionImplies(FC2, C2));
166955a05a2SStanislav Gatev   EXPECT_FALSE(Context.flowConditionImplies(FC1, C2));
167955a05a2SStanislav Gatev }
168955a05a2SStanislav Gatev 
169955a05a2SStanislav Gatev TEST_F(DataflowAnalysisContextTest, JoinFlowConditions) {
170955a05a2SStanislav Gatev   auto &C1 = Context.createAtomicBoolValue();
171955a05a2SStanislav Gatev   auto &C2 = Context.createAtomicBoolValue();
172955a05a2SStanislav Gatev   auto &C3 = Context.createAtomicBoolValue();
173955a05a2SStanislav Gatev 
174955a05a2SStanislav Gatev   auto &FC1 = Context.makeFlowConditionToken();
175955a05a2SStanislav Gatev   Context.addFlowConditionConstraint(FC1, C1);
176955a05a2SStanislav Gatev   Context.addFlowConditionConstraint(FC1, C3);
177955a05a2SStanislav Gatev 
178955a05a2SStanislav Gatev   auto &FC2 = Context.makeFlowConditionToken();
179955a05a2SStanislav Gatev   Context.addFlowConditionConstraint(FC2, C2);
180955a05a2SStanislav Gatev   Context.addFlowConditionConstraint(FC2, C3);
181955a05a2SStanislav Gatev 
182955a05a2SStanislav Gatev   auto &FC3 = Context.joinFlowConditions(FC1, FC2);
183955a05a2SStanislav Gatev   EXPECT_FALSE(Context.flowConditionImplies(FC3, C1));
184955a05a2SStanislav Gatev   EXPECT_FALSE(Context.flowConditionImplies(FC3, C2));
185955a05a2SStanislav Gatev   EXPECT_TRUE(Context.flowConditionImplies(FC3, C3));
186955a05a2SStanislav Gatev }
187955a05a2SStanislav Gatev 
18858abe36aSEric Li TEST_F(DataflowAnalysisContextTest, FlowConditionTautologies) {
18958abe36aSEric Li   // Fresh flow condition with empty/no constraints is always true.
19058abe36aSEric Li   auto &FC1 = Context.makeFlowConditionToken();
19158abe36aSEric Li   EXPECT_TRUE(Context.flowConditionIsTautology(FC1));
19258abe36aSEric Li 
19358abe36aSEric Li   // Literal `true` is always true.
19458abe36aSEric Li   auto &FC2 = Context.makeFlowConditionToken();
19558abe36aSEric Li   Context.addFlowConditionConstraint(FC2, Context.getBoolLiteralValue(true));
19658abe36aSEric Li   EXPECT_TRUE(Context.flowConditionIsTautology(FC2));
19758abe36aSEric Li 
19858abe36aSEric Li   // Literal `false` is never true.
19958abe36aSEric Li   auto &FC3 = Context.makeFlowConditionToken();
20058abe36aSEric Li   Context.addFlowConditionConstraint(FC3, Context.getBoolLiteralValue(false));
20158abe36aSEric Li   EXPECT_FALSE(Context.flowConditionIsTautology(FC3));
20258abe36aSEric Li 
20358abe36aSEric Li   // We can't prove that an arbitrary bool A is always true...
20458abe36aSEric Li   auto &C1 = Context.createAtomicBoolValue();
20558abe36aSEric Li   auto &FC4 = Context.makeFlowConditionToken();
20658abe36aSEric Li   Context.addFlowConditionConstraint(FC4, C1);
20758abe36aSEric Li   EXPECT_FALSE(Context.flowConditionIsTautology(FC4));
20858abe36aSEric Li 
20958abe36aSEric Li   // ... but we can prove A || !A is true.
21058abe36aSEric Li   auto &FC5 = Context.makeFlowConditionToken();
21158abe36aSEric Li   Context.addFlowConditionConstraint(
21200e9d534SWei Yi Tee       FC5, Context.getOrCreateDisjunction(C1, Context.getOrCreateNegation(C1)));
21358abe36aSEric Li   EXPECT_TRUE(Context.flowConditionIsTautology(FC5));
21458abe36aSEric Li }
21558abe36aSEric Li 
2160f65a3e6SWei Yi Tee TEST_F(DataflowAnalysisContextTest, EquivBoolVals) {
2170f65a3e6SWei Yi Tee   auto &X = Context.createAtomicBoolValue();
2180f65a3e6SWei Yi Tee   auto &Y = Context.createAtomicBoolValue();
2190f65a3e6SWei Yi Tee   auto &Z = Context.createAtomicBoolValue();
2200f65a3e6SWei Yi Tee   auto &True = Context.getBoolLiteralValue(true);
2210f65a3e6SWei Yi Tee   auto &False = Context.getBoolLiteralValue(false);
2220f65a3e6SWei Yi Tee 
2230f65a3e6SWei Yi Tee   // X == X
2240f65a3e6SWei Yi Tee   EXPECT_TRUE(Context.equivalentBoolValues(X, X));
2250f65a3e6SWei Yi Tee   // X != Y
2260f65a3e6SWei Yi Tee   EXPECT_FALSE(Context.equivalentBoolValues(X, Y));
2270f65a3e6SWei Yi Tee 
2280f65a3e6SWei Yi Tee   // !X != X
2290f65a3e6SWei Yi Tee   EXPECT_FALSE(Context.equivalentBoolValues(Context.getOrCreateNegation(X), X));
2300f65a3e6SWei Yi Tee   // !(!X) = X
2310f65a3e6SWei Yi Tee   EXPECT_TRUE(Context.equivalentBoolValues(
2320f65a3e6SWei Yi Tee       Context.getOrCreateNegation(Context.getOrCreateNegation(X)), X));
2330f65a3e6SWei Yi Tee 
2340f65a3e6SWei Yi Tee   // (X || X) == X
2350f65a3e6SWei Yi Tee   EXPECT_TRUE(
2360f65a3e6SWei Yi Tee       Context.equivalentBoolValues(Context.getOrCreateDisjunction(X, X), X));
2370f65a3e6SWei Yi Tee   // (X || Y) != X
2380f65a3e6SWei Yi Tee   EXPECT_FALSE(
2390f65a3e6SWei Yi Tee       Context.equivalentBoolValues(Context.getOrCreateDisjunction(X, Y), X));
2400f65a3e6SWei Yi Tee   // (X || True) == True
2410f65a3e6SWei Yi Tee   EXPECT_TRUE(Context.equivalentBoolValues(
2420f65a3e6SWei Yi Tee       Context.getOrCreateDisjunction(X, True), True));
2430f65a3e6SWei Yi Tee   // (X || False) == X
2440f65a3e6SWei Yi Tee   EXPECT_TRUE(Context.equivalentBoolValues(
2450f65a3e6SWei Yi Tee       Context.getOrCreateDisjunction(X, False), X));
2460f65a3e6SWei Yi Tee 
2470f65a3e6SWei Yi Tee   // (X && X) == X
2480f65a3e6SWei Yi Tee   EXPECT_TRUE(
2490f65a3e6SWei Yi Tee       Context.equivalentBoolValues(Context.getOrCreateConjunction(X, X), X));
2500f65a3e6SWei Yi Tee   // (X && Y) != X
2510f65a3e6SWei Yi Tee   EXPECT_FALSE(
2520f65a3e6SWei Yi Tee       Context.equivalentBoolValues(Context.getOrCreateConjunction(X, Y), X));
2530f65a3e6SWei Yi Tee   // (X && True) == X
2540f65a3e6SWei Yi Tee   EXPECT_TRUE(
2550f65a3e6SWei Yi Tee       Context.equivalentBoolValues(Context.getOrCreateConjunction(X, True), X));
2560f65a3e6SWei Yi Tee   // (X && False) == False
2570f65a3e6SWei Yi Tee   EXPECT_TRUE(Context.equivalentBoolValues(
2580f65a3e6SWei Yi Tee       Context.getOrCreateConjunction(X, False), False));
2590f65a3e6SWei Yi Tee 
2600f65a3e6SWei Yi Tee   // (X || Y) == (Y || X)
2610f65a3e6SWei Yi Tee   EXPECT_TRUE(
2620f65a3e6SWei Yi Tee       Context.equivalentBoolValues(Context.getOrCreateDisjunction(X, Y),
2630f65a3e6SWei Yi Tee                                    Context.getOrCreateDisjunction(Y, X)));
2640f65a3e6SWei Yi Tee   // (X && Y) == (Y && X)
2650f65a3e6SWei Yi Tee   EXPECT_TRUE(
2660f65a3e6SWei Yi Tee       Context.equivalentBoolValues(Context.getOrCreateConjunction(X, Y),
2670f65a3e6SWei Yi Tee                                    Context.getOrCreateConjunction(Y, X)));
2680f65a3e6SWei Yi Tee 
2690f65a3e6SWei Yi Tee   // ((X || Y) || Z) == (X || (Y || Z))
2700f65a3e6SWei Yi Tee   EXPECT_TRUE(Context.equivalentBoolValues(
2710f65a3e6SWei Yi Tee       Context.getOrCreateDisjunction(Context.getOrCreateDisjunction(X, Y), Z),
2720f65a3e6SWei Yi Tee       Context.getOrCreateDisjunction(X, Context.getOrCreateDisjunction(Y, Z))));
2730f65a3e6SWei Yi Tee   // ((X && Y) && Z) == (X && (Y && Z))
2740f65a3e6SWei Yi Tee   EXPECT_TRUE(Context.equivalentBoolValues(
2750f65a3e6SWei Yi Tee       Context.getOrCreateConjunction(Context.getOrCreateConjunction(X, Y), Z),
2760f65a3e6SWei Yi Tee       Context.getOrCreateConjunction(X, Context.getOrCreateConjunction(Y, Z))));
2770f65a3e6SWei Yi Tee }
2780f65a3e6SWei Yi Tee 
279*bdfe556dSWei Yi Tee TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionsAtomicFC) {
280*bdfe556dSWei Yi Tee   auto &X = Context.createAtomicBoolValue();
281*bdfe556dSWei Yi Tee   auto &True = Context.getBoolLiteralValue(true);
282*bdfe556dSWei Yi Tee   auto &False = Context.getBoolLiteralValue(false);
283*bdfe556dSWei Yi Tee 
284*bdfe556dSWei Yi Tee   // FC = X
285*bdfe556dSWei Yi Tee   auto &FC = Context.makeFlowConditionToken();
286*bdfe556dSWei Yi Tee   Context.addFlowConditionConstraint(FC, X);
287*bdfe556dSWei Yi Tee 
288*bdfe556dSWei Yi Tee   // If X is true in FC, FC = X must be true
289*bdfe556dSWei Yi Tee   auto &FCWithXTrue =
290*bdfe556dSWei Yi Tee       Context.buildAndSubstituteFlowCondition(FC, {{&X, &True}});
291*bdfe556dSWei Yi Tee   EXPECT_TRUE(Context.equivalentBoolValues(FCWithXTrue, True));
292*bdfe556dSWei Yi Tee 
293*bdfe556dSWei Yi Tee   // If X is false in FC, FC = X must be false
294*bdfe556dSWei Yi Tee   auto &FC1WithXFalse =
295*bdfe556dSWei Yi Tee       Context.buildAndSubstituteFlowCondition(FC, {{&X, &False}});
296*bdfe556dSWei Yi Tee   EXPECT_TRUE(Context.equivalentBoolValues(FC1WithXFalse, False));
297*bdfe556dSWei Yi Tee }
298*bdfe556dSWei Yi Tee 
299*bdfe556dSWei Yi Tee TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionsNegatedFC) {
300*bdfe556dSWei Yi Tee   auto &X = Context.createAtomicBoolValue();
301*bdfe556dSWei Yi Tee   auto &True = Context.getBoolLiteralValue(true);
302*bdfe556dSWei Yi Tee   auto &False = Context.getBoolLiteralValue(false);
303*bdfe556dSWei Yi Tee 
304*bdfe556dSWei Yi Tee   // FC = !X
305*bdfe556dSWei Yi Tee   auto &FC = Context.makeFlowConditionToken();
306*bdfe556dSWei Yi Tee   Context.addFlowConditionConstraint(FC, Context.getOrCreateNegation(X));
307*bdfe556dSWei Yi Tee 
308*bdfe556dSWei Yi Tee   // If X is true in FC, FC = !X must be false
309*bdfe556dSWei Yi Tee   auto &FCWithXTrue =
310*bdfe556dSWei Yi Tee       Context.buildAndSubstituteFlowCondition(FC, {{&X, &True}});
311*bdfe556dSWei Yi Tee   EXPECT_TRUE(Context.equivalentBoolValues(FCWithXTrue, False));
312*bdfe556dSWei Yi Tee 
313*bdfe556dSWei Yi Tee   // If X is false in FC, FC = !X must be true
314*bdfe556dSWei Yi Tee   auto &FC1WithXFalse =
315*bdfe556dSWei Yi Tee       Context.buildAndSubstituteFlowCondition(FC, {{&X, &False}});
316*bdfe556dSWei Yi Tee   EXPECT_TRUE(Context.equivalentBoolValues(FC1WithXFalse, True));
317*bdfe556dSWei Yi Tee }
318*bdfe556dSWei Yi Tee 
319*bdfe556dSWei Yi Tee TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionsDisjunctiveFC) {
320*bdfe556dSWei Yi Tee   auto &X = Context.createAtomicBoolValue();
321*bdfe556dSWei Yi Tee   auto &Y = Context.createAtomicBoolValue();
322*bdfe556dSWei Yi Tee   auto &True = Context.getBoolLiteralValue(true);
323*bdfe556dSWei Yi Tee   auto &False = Context.getBoolLiteralValue(false);
324*bdfe556dSWei Yi Tee 
325*bdfe556dSWei Yi Tee   // FC = X || Y
326*bdfe556dSWei Yi Tee   auto &FC = Context.makeFlowConditionToken();
327*bdfe556dSWei Yi Tee   Context.addFlowConditionConstraint(FC, Context.getOrCreateDisjunction(X, Y));
328*bdfe556dSWei Yi Tee 
329*bdfe556dSWei Yi Tee   // If X is true in FC, FC = X || Y must be true
330*bdfe556dSWei Yi Tee   auto &FCWithXTrue =
331*bdfe556dSWei Yi Tee       Context.buildAndSubstituteFlowCondition(FC, {{&X, &True}});
332*bdfe556dSWei Yi Tee   EXPECT_TRUE(Context.equivalentBoolValues(FCWithXTrue, True));
333*bdfe556dSWei Yi Tee 
334*bdfe556dSWei Yi Tee   // If X is false in FC, FC = X || Y is equivalent to evaluating Y
335*bdfe556dSWei Yi Tee   auto &FC1WithXFalse =
336*bdfe556dSWei Yi Tee       Context.buildAndSubstituteFlowCondition(FC, {{&X, &False}});
337*bdfe556dSWei Yi Tee   EXPECT_TRUE(Context.equivalentBoolValues(FC1WithXFalse, Y));
338*bdfe556dSWei Yi Tee }
339*bdfe556dSWei Yi Tee 
340*bdfe556dSWei Yi Tee TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionsConjunctiveFC) {
341*bdfe556dSWei Yi Tee   auto &X = Context.createAtomicBoolValue();
342*bdfe556dSWei Yi Tee   auto &Y = Context.createAtomicBoolValue();
343*bdfe556dSWei Yi Tee   auto &True = Context.getBoolLiteralValue(true);
344*bdfe556dSWei Yi Tee   auto &False = Context.getBoolLiteralValue(false);
345*bdfe556dSWei Yi Tee 
346*bdfe556dSWei Yi Tee   // FC = X && Y
347*bdfe556dSWei Yi Tee   auto &FC = Context.makeFlowConditionToken();
348*bdfe556dSWei Yi Tee   Context.addFlowConditionConstraint(FC, Context.getOrCreateConjunction(X, Y));
349*bdfe556dSWei Yi Tee 
350*bdfe556dSWei Yi Tee   // If X is true in FC, FC = X && Y is equivalent to evaluating Y
351*bdfe556dSWei Yi Tee   auto &FCWithXTrue =
352*bdfe556dSWei Yi Tee       Context.buildAndSubstituteFlowCondition(FC, {{&X, &True}});
353*bdfe556dSWei Yi Tee   EXPECT_TRUE(Context.equivalentBoolValues(FCWithXTrue, Y));
354*bdfe556dSWei Yi Tee 
355*bdfe556dSWei Yi Tee   // If X is false in FC, FC = X && Y must be false
356*bdfe556dSWei Yi Tee   auto &FCWithXFalse =
357*bdfe556dSWei Yi Tee       Context.buildAndSubstituteFlowCondition(FC, {{&X, &False}});
358*bdfe556dSWei Yi Tee   EXPECT_TRUE(Context.equivalentBoolValues(FCWithXFalse, False));
359*bdfe556dSWei Yi Tee }
360*bdfe556dSWei Yi Tee 
361*bdfe556dSWei Yi Tee TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionsForkedFC) {
362*bdfe556dSWei Yi Tee   auto &X = Context.createAtomicBoolValue();
363*bdfe556dSWei Yi Tee   auto &Y = Context.createAtomicBoolValue();
364*bdfe556dSWei Yi Tee   auto &Z = Context.createAtomicBoolValue();
365*bdfe556dSWei Yi Tee   auto &True = Context.getBoolLiteralValue(true);
366*bdfe556dSWei Yi Tee   auto &False = Context.getBoolLiteralValue(false);
367*bdfe556dSWei Yi Tee 
368*bdfe556dSWei Yi Tee   // FC = X && Y
369*bdfe556dSWei Yi Tee   auto &FC = Context.makeFlowConditionToken();
370*bdfe556dSWei Yi Tee   Context.addFlowConditionConstraint(FC, Context.getOrCreateConjunction(X, Y));
371*bdfe556dSWei Yi Tee   // ForkedFC = FC && Z = X && Y && Z
372*bdfe556dSWei Yi Tee   auto &ForkedFC = Context.forkFlowCondition(FC);
373*bdfe556dSWei Yi Tee   Context.addFlowConditionConstraint(ForkedFC, Z);
374*bdfe556dSWei Yi Tee 
375*bdfe556dSWei Yi Tee   // If any of X,Y,Z is true in ForkedFC, ForkedFC = X && Y && Z is equivalent
376*bdfe556dSWei Yi Tee   // to evaluating the conjunction of the remaining values
377*bdfe556dSWei Yi Tee   auto &ForkedFCWithZTrue =
378*bdfe556dSWei Yi Tee       Context.buildAndSubstituteFlowCondition(ForkedFC, {{&Z, &True}});
379*bdfe556dSWei Yi Tee   EXPECT_TRUE(Context.equivalentBoolValues(
380*bdfe556dSWei Yi Tee       ForkedFCWithZTrue, Context.getOrCreateConjunction(X, Y)));
381*bdfe556dSWei Yi Tee   auto &ForkedFCWithYAndZTrue = Context.buildAndSubstituteFlowCondition(
382*bdfe556dSWei Yi Tee       ForkedFC, {{&Y, &True}, {&Z, &True}});
383*bdfe556dSWei Yi Tee   EXPECT_TRUE(Context.equivalentBoolValues(ForkedFCWithYAndZTrue, X));
384*bdfe556dSWei Yi Tee 
385*bdfe556dSWei Yi Tee   // If any of X,Y,Z is false in ForkedFC, ForkedFC = X && Y && Z must be false
386*bdfe556dSWei Yi Tee   auto &ForkedFCWithXFalse =
387*bdfe556dSWei Yi Tee       Context.buildAndSubstituteFlowCondition(ForkedFC, {{&X, &False}});
388*bdfe556dSWei Yi Tee   auto &ForkedFCWithYFalse =
389*bdfe556dSWei Yi Tee       Context.buildAndSubstituteFlowCondition(ForkedFC, {{&Y, &False}});
390*bdfe556dSWei Yi Tee   auto &ForkedFCWithZFalse =
391*bdfe556dSWei Yi Tee       Context.buildAndSubstituteFlowCondition(ForkedFC, {{&Z, &False}});
392*bdfe556dSWei Yi Tee   EXPECT_TRUE(Context.equivalentBoolValues(ForkedFCWithXFalse, False));
393*bdfe556dSWei Yi Tee   EXPECT_TRUE(Context.equivalentBoolValues(ForkedFCWithYFalse, False));
394*bdfe556dSWei Yi Tee   EXPECT_TRUE(Context.equivalentBoolValues(ForkedFCWithZFalse, False));
395*bdfe556dSWei Yi Tee }
396*bdfe556dSWei Yi Tee 
397*bdfe556dSWei Yi Tee TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionsJoinedFC) {
398*bdfe556dSWei Yi Tee   auto &X = Context.createAtomicBoolValue();
399*bdfe556dSWei Yi Tee   auto &Y = Context.createAtomicBoolValue();
400*bdfe556dSWei Yi Tee   auto &Z = Context.createAtomicBoolValue();
401*bdfe556dSWei Yi Tee   auto &True = Context.getBoolLiteralValue(true);
402*bdfe556dSWei Yi Tee   auto &False = Context.getBoolLiteralValue(false);
403*bdfe556dSWei Yi Tee 
404*bdfe556dSWei Yi Tee   // FC1 = X
405*bdfe556dSWei Yi Tee   auto &FC1 = Context.makeFlowConditionToken();
406*bdfe556dSWei Yi Tee   Context.addFlowConditionConstraint(FC1, X);
407*bdfe556dSWei Yi Tee   // FC2 = Y
408*bdfe556dSWei Yi Tee   auto &FC2 = Context.makeFlowConditionToken();
409*bdfe556dSWei Yi Tee   Context.addFlowConditionConstraint(FC2, Y);
410*bdfe556dSWei Yi Tee   // JoinedFC = (FC1 || FC2) && Z = (X || Y) && Z
411*bdfe556dSWei Yi Tee   auto &JoinedFC = Context.joinFlowConditions(FC1, FC2);
412*bdfe556dSWei Yi Tee   Context.addFlowConditionConstraint(JoinedFC, Z);
413*bdfe556dSWei Yi Tee 
414*bdfe556dSWei Yi Tee   // If any of X, Y is true in JoinedFC, JoinedFC = (X || Y) && Z is equivalent
415*bdfe556dSWei Yi Tee   // to evaluating the remaining Z
416*bdfe556dSWei Yi Tee   auto &JoinedFCWithXTrue =
417*bdfe556dSWei Yi Tee       Context.buildAndSubstituteFlowCondition(JoinedFC, {{&X, &True}});
418*bdfe556dSWei Yi Tee   auto &JoinedFCWithYTrue =
419*bdfe556dSWei Yi Tee       Context.buildAndSubstituteFlowCondition(JoinedFC, {{&Y, &True}});
420*bdfe556dSWei Yi Tee   EXPECT_TRUE(Context.equivalentBoolValues(JoinedFCWithXTrue, Z));
421*bdfe556dSWei Yi Tee   EXPECT_TRUE(Context.equivalentBoolValues(JoinedFCWithYTrue, Z));
422*bdfe556dSWei Yi Tee 
423*bdfe556dSWei Yi Tee   // If Z is true in JoinedFC, JoinedFC = (X || Y) && Z is equivalent to
424*bdfe556dSWei Yi Tee   // evaluating the remaining disjunction (X || Y)
425*bdfe556dSWei Yi Tee   auto &JoinedFCWithZTrue =
426*bdfe556dSWei Yi Tee       Context.buildAndSubstituteFlowCondition(JoinedFC, {{&Z, &True}});
427*bdfe556dSWei Yi Tee   EXPECT_TRUE(Context.equivalentBoolValues(
428*bdfe556dSWei Yi Tee       JoinedFCWithZTrue, Context.getOrCreateDisjunction(X, Y)));
429*bdfe556dSWei Yi Tee 
430*bdfe556dSWei Yi Tee   // If any of X, Y is false in JoinedFC, JoinedFC = (X || Y) && Z is equivalent
431*bdfe556dSWei Yi Tee   // to evaluating the conjunction of the other value and Z
432*bdfe556dSWei Yi Tee   auto &JoinedFCWithXFalse =
433*bdfe556dSWei Yi Tee       Context.buildAndSubstituteFlowCondition(JoinedFC, {{&X, &False}});
434*bdfe556dSWei Yi Tee   auto &JoinedFCWithYFalse =
435*bdfe556dSWei Yi Tee       Context.buildAndSubstituteFlowCondition(JoinedFC, {{&Y, &False}});
436*bdfe556dSWei Yi Tee   EXPECT_TRUE(Context.equivalentBoolValues(
437*bdfe556dSWei Yi Tee       JoinedFCWithXFalse, Context.getOrCreateConjunction(Y, Z)));
438*bdfe556dSWei Yi Tee   EXPECT_TRUE(Context.equivalentBoolValues(
439*bdfe556dSWei Yi Tee       JoinedFCWithYFalse, Context.getOrCreateConjunction(X, Z)));
440*bdfe556dSWei Yi Tee 
441*bdfe556dSWei Yi Tee   // If Z is false in JoinedFC, JoinedFC = (X || Y) && Z must be false
442*bdfe556dSWei Yi Tee   auto &JoinedFCWithZFalse =
443*bdfe556dSWei Yi Tee       Context.buildAndSubstituteFlowCondition(JoinedFC, {{&Z, &False}});
444*bdfe556dSWei Yi Tee   EXPECT_TRUE(Context.equivalentBoolValues(JoinedFCWithZFalse, False));
445*bdfe556dSWei Yi Tee }
446*bdfe556dSWei Yi Tee 
447ae60884dSStanislav Gatev } // namespace
448