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