1 //===- PhiValuesTest.cpp - PhiValues unit tests ---------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Analysis/PhiValues.h"
10 #include "llvm/IR/BasicBlock.h"
11 #include "llvm/IR/Constants.h"
12 #include "llvm/IR/Function.h"
13 #include "llvm/IR/Instructions.h"
14 #include "llvm/IR/Module.h"
15 #include "llvm/IR/Type.h"
16 #include "gtest/gtest.h"
20 TEST(PhiValuesTest
, SimplePhi
) {
22 Module
M("PhiValuesTest", C
);
24 Type
*VoidTy
= Type::getVoidTy(C
);
25 Type
*I1Ty
= Type::getInt1Ty(C
);
26 Type
*I32Ty
= Type::getInt32Ty(C
);
27 Type
*PtrTy
= PointerType::get(C
, 0);
29 // Create a function with phis that do not have other phis as incoming values
30 Function
*F
= Function::Create(FunctionType::get(VoidTy
, false),
31 Function::ExternalLinkage
, "f", M
);
33 BasicBlock
*Entry
= BasicBlock::Create(C
, "entry", F
);
34 BasicBlock
*If
= BasicBlock::Create(C
, "if", F
);
35 BasicBlock
*Else
= BasicBlock::Create(C
, "else", F
);
36 BasicBlock
*Then
= BasicBlock::Create(C
, "then", F
);
37 BranchInst::Create(If
, Else
, PoisonValue::get(I1Ty
), Entry
);
38 BranchInst::Create(Then
, If
);
39 BranchInst::Create(Then
, Else
);
41 Value
*Val1
= new LoadInst(I32Ty
, PoisonValue::get(PtrTy
), "val1", Entry
);
42 Value
*Val2
= new LoadInst(I32Ty
, PoisonValue::get(PtrTy
), "val2", Entry
);
43 Value
*Val3
= new LoadInst(I32Ty
, PoisonValue::get(PtrTy
), "val3", Entry
);
44 Value
*Val4
= new LoadInst(I32Ty
, PoisonValue::get(PtrTy
), "val4", Entry
);
46 PHINode
*Phi1
= PHINode::Create(I32Ty
, 2, "phi1", Then
);
47 Phi1
->addIncoming(Val1
, If
);
48 Phi1
->addIncoming(Val2
, Else
);
49 PHINode
*Phi2
= PHINode::Create(I32Ty
, 2, "phi2", Then
);
50 Phi2
->addIncoming(Val1
, If
);
51 Phi2
->addIncoming(Val3
, Else
);
54 PhiValues::ValueSet Vals
;
56 // Check that simple usage works
57 Vals
= PV
.getValuesForPhi(Phi1
);
58 EXPECT_EQ(Vals
.size(), 2u);
59 EXPECT_TRUE(Vals
.count(Val1
));
60 EXPECT_TRUE(Vals
.count(Val2
));
61 Vals
= PV
.getValuesForPhi(Phi2
);
62 EXPECT_EQ(Vals
.size(), 2u);
63 EXPECT_TRUE(Vals
.count(Val1
));
64 EXPECT_TRUE(Vals
.count(Val3
));
66 // Check that values are updated when one value is replaced with another
67 Val1
->replaceAllUsesWith(Val4
);
68 PV
.invalidateValue(Val1
);
69 Vals
= PV
.getValuesForPhi(Phi1
);
70 EXPECT_EQ(Vals
.size(), 2u);
71 EXPECT_TRUE(Vals
.count(Val4
));
72 EXPECT_TRUE(Vals
.count(Val2
));
73 Vals
= PV
.getValuesForPhi(Phi2
);
74 EXPECT_EQ(Vals
.size(), 2u);
75 EXPECT_TRUE(Vals
.count(Val4
));
76 EXPECT_TRUE(Vals
.count(Val3
));
78 // Check that setting in incoming value directly updates the values
79 Phi1
->setIncomingValue(0, Val1
);
80 PV
.invalidateValue(Phi1
);
81 Vals
= PV
.getValuesForPhi(Phi1
);
82 EXPECT_EQ(Vals
.size(), 2u);
83 EXPECT_TRUE(Vals
.count(Val1
));
84 EXPECT_TRUE(Vals
.count(Val2
));
87 TEST(PhiValuesTest
, DependentPhi
) {
89 Module
M("PhiValuesTest", C
);
91 Type
*VoidTy
= Type::getVoidTy(C
);
92 Type
*I1Ty
= Type::getInt1Ty(C
);
93 Type
*I32Ty
= Type::getInt32Ty(C
);
94 Type
*PtrTy
= PointerType::get(C
, 0);
96 // Create a function with a phi that has another phi as an incoming value
97 Function
*F
= Function::Create(FunctionType::get(VoidTy
, false),
98 Function::ExternalLinkage
, "f", M
);
100 BasicBlock
*Entry
= BasicBlock::Create(C
, "entry", F
);
101 BasicBlock
*If1
= BasicBlock::Create(C
, "if1", F
);
102 BasicBlock
*Else1
= BasicBlock::Create(C
, "else1", F
);
103 BasicBlock
*Then
= BasicBlock::Create(C
, "then", F
);
104 BasicBlock
*If2
= BasicBlock::Create(C
, "if2", F
);
105 BasicBlock
*Else2
= BasicBlock::Create(C
, "else2", F
);
106 BasicBlock
*End
= BasicBlock::Create(C
, "then", F
);
107 BranchInst::Create(If1
, Else1
, PoisonValue::get(I1Ty
), Entry
);
108 BranchInst::Create(Then
, If1
);
109 BranchInst::Create(Then
, Else1
);
110 BranchInst::Create(If2
, Else2
, PoisonValue::get(I1Ty
), Then
);
111 BranchInst::Create(End
, If2
);
112 BranchInst::Create(End
, Else2
);
114 Value
*Val1
= new LoadInst(I32Ty
, PoisonValue::get(PtrTy
), "val1", Entry
);
115 Value
*Val2
= new LoadInst(I32Ty
, PoisonValue::get(PtrTy
), "val2", Entry
);
116 Value
*Val3
= new LoadInst(I32Ty
, PoisonValue::get(PtrTy
), "val3", Entry
);
117 Value
*Val4
= new LoadInst(I32Ty
, PoisonValue::get(PtrTy
), "val4", Entry
);
119 PHINode
*Phi1
= PHINode::Create(I32Ty
, 2, "phi1", Then
);
120 Phi1
->addIncoming(Val1
, If1
);
121 Phi1
->addIncoming(Val2
, Else1
);
122 PHINode
*Phi2
= PHINode::Create(I32Ty
, 2, "phi2", Then
);
123 Phi2
->addIncoming(Val2
, If1
);
124 Phi2
->addIncoming(Val3
, Else1
);
125 PHINode
*Phi3
= PHINode::Create(I32Ty
, 2, "phi3", End
);
126 Phi3
->addIncoming(Phi1
, If2
);
127 Phi3
->addIncoming(Val3
, Else2
);
130 PhiValues::ValueSet Vals
;
132 // Check that simple usage works
133 Vals
= PV
.getValuesForPhi(Phi1
);
134 EXPECT_EQ(Vals
.size(), 2u);
135 EXPECT_TRUE(Vals
.count(Val1
));
136 EXPECT_TRUE(Vals
.count(Val2
));
137 Vals
= PV
.getValuesForPhi(Phi2
);
138 EXPECT_EQ(Vals
.size(), 2u);
139 EXPECT_TRUE(Vals
.count(Val2
));
140 EXPECT_TRUE(Vals
.count(Val3
));
141 Vals
= PV
.getValuesForPhi(Phi3
);
142 EXPECT_EQ(Vals
.size(), 3u);
143 EXPECT_TRUE(Vals
.count(Val1
));
144 EXPECT_TRUE(Vals
.count(Val2
));
145 EXPECT_TRUE(Vals
.count(Val3
));
147 // Check that changing an incoming value in the dependent phi changes the depending phi
148 Phi1
->setIncomingValue(0, Val4
);
149 PV
.invalidateValue(Phi1
);
150 Vals
= PV
.getValuesForPhi(Phi1
);
151 EXPECT_EQ(Vals
.size(), 2u);
152 EXPECT_TRUE(Vals
.count(Val4
));
153 EXPECT_TRUE(Vals
.count(Val2
));
154 Vals
= PV
.getValuesForPhi(Phi2
);
155 EXPECT_EQ(Vals
.size(), 2u);
156 EXPECT_TRUE(Vals
.count(Val2
));
157 EXPECT_TRUE(Vals
.count(Val3
));
158 Vals
= PV
.getValuesForPhi(Phi3
);
159 EXPECT_EQ(Vals
.size(), 3u);
160 EXPECT_TRUE(Vals
.count(Val4
));
161 EXPECT_TRUE(Vals
.count(Val2
));
162 EXPECT_TRUE(Vals
.count(Val3
));
164 // Check that replacing an incoming phi with a value works
165 Phi3
->setIncomingValue(0, Val1
);
166 PV
.invalidateValue(Phi3
);
167 Vals
= PV
.getValuesForPhi(Phi1
);
168 EXPECT_EQ(Vals
.size(), 2u);
169 EXPECT_TRUE(Vals
.count(Val4
));
170 EXPECT_TRUE(Vals
.count(Val2
));
171 Vals
= PV
.getValuesForPhi(Phi2
);
172 EXPECT_EQ(Vals
.size(), 2u);
173 EXPECT_TRUE(Vals
.count(Val2
));
174 EXPECT_TRUE(Vals
.count(Val3
));
175 Vals
= PV
.getValuesForPhi(Phi3
);
176 EXPECT_EQ(Vals
.size(), 2u);
177 EXPECT_TRUE(Vals
.count(Val1
));
178 EXPECT_TRUE(Vals
.count(Val3
));
180 // Check that adding a phi as an incoming value works
181 Phi3
->setIncomingValue(1, Phi2
);
182 PV
.invalidateValue(Phi3
);
183 Vals
= PV
.getValuesForPhi(Phi1
);
184 EXPECT_EQ(Vals
.size(), 2u);
185 EXPECT_TRUE(Vals
.count(Val4
));
186 EXPECT_TRUE(Vals
.count(Val2
));
187 Vals
= PV
.getValuesForPhi(Phi2
);
188 EXPECT_EQ(Vals
.size(), 2u);
189 EXPECT_TRUE(Vals
.count(Val2
));
190 EXPECT_TRUE(Vals
.count(Val3
));
191 Vals
= PV
.getValuesForPhi(Phi3
);
192 EXPECT_EQ(Vals
.size(), 3u);
193 EXPECT_TRUE(Vals
.count(Val1
));
194 EXPECT_TRUE(Vals
.count(Val2
));
195 EXPECT_TRUE(Vals
.count(Val3
));
197 // Check that replacing an incoming phi then deleting it works
198 Phi3
->setIncomingValue(1, Val2
);
199 PV
.invalidateValue(Phi2
);
200 Phi2
->eraseFromParent();
201 PV
.invalidateValue(Phi3
);
202 Vals
= PV
.getValuesForPhi(Phi1
);
203 EXPECT_EQ(Vals
.size(), 2u);
204 EXPECT_TRUE(Vals
.count(Val4
));
205 EXPECT_TRUE(Vals
.count(Val2
));
206 Vals
= PV
.getValuesForPhi(Phi3
);
207 EXPECT_EQ(Vals
.size(), 2u);
208 EXPECT_TRUE(Vals
.count(Val1
));
209 EXPECT_TRUE(Vals
.count(Val2
));