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