1bdbbd838SJohn Brawn //===- PhiValuesTest.cpp - PhiValues unit tests ---------------------------===//
2bdbbd838SJohn Brawn //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bdbbd838SJohn Brawn //
7bdbbd838SJohn Brawn //===----------------------------------------------------------------------===//
8bdbbd838SJohn Brawn
9bdbbd838SJohn Brawn #include "llvm/Analysis/PhiValues.h"
10bdbbd838SJohn Brawn #include "llvm/IR/BasicBlock.h"
11*823b32fbSBill Wendling #include "llvm/IR/Constants.h"
12bdbbd838SJohn Brawn #include "llvm/IR/Function.h"
13bdbbd838SJohn Brawn #include "llvm/IR/Instructions.h"
14bdbbd838SJohn Brawn #include "llvm/IR/Module.h"
15bdbbd838SJohn Brawn #include "llvm/IR/Type.h"
16bdbbd838SJohn Brawn #include "gtest/gtest.h"
17bdbbd838SJohn Brawn
18bdbbd838SJohn Brawn using namespace llvm;
19bdbbd838SJohn Brawn
TEST(PhiValuesTest,SimplePhi)20bdbbd838SJohn Brawn TEST(PhiValuesTest, SimplePhi) {
21bdbbd838SJohn Brawn LLVMContext C;
22bdbbd838SJohn Brawn Module M("PhiValuesTest", C);
23bdbbd838SJohn Brawn
24bdbbd838SJohn Brawn Type *VoidTy = Type::getVoidTy(C);
25bdbbd838SJohn Brawn Type *I1Ty = Type::getInt1Ty(C);
26bdbbd838SJohn Brawn Type *I32Ty = Type::getInt32Ty(C);
27bdbbd838SJohn Brawn Type *I32PtrTy = Type::getInt32PtrTy(C);
28bdbbd838SJohn Brawn
29bdbbd838SJohn Brawn // Create a function with phis that do not have other phis as incoming values
3013680223SJames Y Knight Function *F = Function::Create(FunctionType::get(VoidTy, false),
3113680223SJames Y Knight Function::ExternalLinkage, "f", M);
32bdbbd838SJohn Brawn
33bdbbd838SJohn Brawn BasicBlock *Entry = BasicBlock::Create(C, "entry", F);
34bdbbd838SJohn Brawn BasicBlock *If = BasicBlock::Create(C, "if", F);
35bdbbd838SJohn Brawn BasicBlock *Else = BasicBlock::Create(C, "else", F);
36bdbbd838SJohn Brawn BasicBlock *Then = BasicBlock::Create(C, "then", F);
37bdbbd838SJohn Brawn BranchInst::Create(If, Else, UndefValue::get(I1Ty), Entry);
38bdbbd838SJohn Brawn BranchInst::Create(Then, If);
39bdbbd838SJohn Brawn BranchInst::Create(Then, Else);
40bdbbd838SJohn Brawn
4114359ef1SJames Y Knight Value *Val1 = new LoadInst(I32Ty, UndefValue::get(I32PtrTy), "val1", Entry);
4214359ef1SJames Y Knight Value *Val2 = new LoadInst(I32Ty, UndefValue::get(I32PtrTy), "val2", Entry);
4314359ef1SJames Y Knight Value *Val3 = new LoadInst(I32Ty, UndefValue::get(I32PtrTy), "val3", Entry);
4414359ef1SJames Y Knight Value *Val4 = new LoadInst(I32Ty, UndefValue::get(I32PtrTy), "val4", Entry);
45bdbbd838SJohn Brawn
46bdbbd838SJohn Brawn PHINode *Phi1 = PHINode::Create(I32Ty, 2, "phi1", Then);
47bdbbd838SJohn Brawn Phi1->addIncoming(Val1, If);
48bdbbd838SJohn Brawn Phi1->addIncoming(Val2, Else);
49bdbbd838SJohn Brawn PHINode *Phi2 = PHINode::Create(I32Ty, 2, "phi2", Then);
50bdbbd838SJohn Brawn Phi2->addIncoming(Val1, If);
51bdbbd838SJohn Brawn Phi2->addIncoming(Val3, Else);
52bdbbd838SJohn Brawn
53bdbbd838SJohn Brawn PhiValues PV(*F);
54bdbbd838SJohn Brawn PhiValues::ValueSet Vals;
55bdbbd838SJohn Brawn
56bdbbd838SJohn Brawn // Check that simple usage works
57bdbbd838SJohn Brawn Vals = PV.getValuesForPhi(Phi1);
58bdbbd838SJohn Brawn EXPECT_EQ(Vals.size(), 2u);
59bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val1));
60bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val2));
61bdbbd838SJohn Brawn Vals = PV.getValuesForPhi(Phi2);
62bdbbd838SJohn Brawn EXPECT_EQ(Vals.size(), 2u);
63bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val1));
64bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val3));
65bdbbd838SJohn Brawn
66bdbbd838SJohn Brawn // Check that values are updated when one value is replaced with another
67bdbbd838SJohn Brawn Val1->replaceAllUsesWith(Val4);
68bdbbd838SJohn Brawn PV.invalidateValue(Val1);
69bdbbd838SJohn Brawn Vals = PV.getValuesForPhi(Phi1);
70bdbbd838SJohn Brawn EXPECT_EQ(Vals.size(), 2u);
71bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val4));
72bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val2));
73bdbbd838SJohn Brawn Vals = PV.getValuesForPhi(Phi2);
74bdbbd838SJohn Brawn EXPECT_EQ(Vals.size(), 2u);
75bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val4));
76bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val3));
77bdbbd838SJohn Brawn
78bdbbd838SJohn Brawn // Check that setting in incoming value directly updates the values
79bdbbd838SJohn Brawn Phi1->setIncomingValue(0, Val1);
80bdbbd838SJohn Brawn PV.invalidateValue(Phi1);
81bdbbd838SJohn Brawn Vals = PV.getValuesForPhi(Phi1);
82bdbbd838SJohn Brawn EXPECT_EQ(Vals.size(), 2u);
83bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val1));
84bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val2));
85bdbbd838SJohn Brawn }
86bdbbd838SJohn Brawn
TEST(PhiValuesTest,DependentPhi)87bdbbd838SJohn Brawn TEST(PhiValuesTest, DependentPhi) {
88bdbbd838SJohn Brawn LLVMContext C;
89bdbbd838SJohn Brawn Module M("PhiValuesTest", C);
90bdbbd838SJohn Brawn
91bdbbd838SJohn Brawn Type *VoidTy = Type::getVoidTy(C);
92bdbbd838SJohn Brawn Type *I1Ty = Type::getInt1Ty(C);
93bdbbd838SJohn Brawn Type *I32Ty = Type::getInt32Ty(C);
94bdbbd838SJohn Brawn Type *I32PtrTy = Type::getInt32PtrTy(C);
95bdbbd838SJohn Brawn
96bdbbd838SJohn Brawn // Create a function with a phi that has another phi as an incoming value
9713680223SJames Y Knight Function *F = Function::Create(FunctionType::get(VoidTy, false),
9813680223SJames Y Knight Function::ExternalLinkage, "f", M);
99bdbbd838SJohn Brawn
100bdbbd838SJohn Brawn BasicBlock *Entry = BasicBlock::Create(C, "entry", F);
101bdbbd838SJohn Brawn BasicBlock *If1 = BasicBlock::Create(C, "if1", F);
102bdbbd838SJohn Brawn BasicBlock *Else1 = BasicBlock::Create(C, "else1", F);
103bdbbd838SJohn Brawn BasicBlock *Then = BasicBlock::Create(C, "then", F);
104bdbbd838SJohn Brawn BasicBlock *If2 = BasicBlock::Create(C, "if2", F);
105bdbbd838SJohn Brawn BasicBlock *Else2 = BasicBlock::Create(C, "else2", F);
106bdbbd838SJohn Brawn BasicBlock *End = BasicBlock::Create(C, "then", F);
107bdbbd838SJohn Brawn BranchInst::Create(If1, Else1, UndefValue::get(I1Ty), Entry);
108bdbbd838SJohn Brawn BranchInst::Create(Then, If1);
109bdbbd838SJohn Brawn BranchInst::Create(Then, Else1);
110bdbbd838SJohn Brawn BranchInst::Create(If2, Else2, UndefValue::get(I1Ty), Then);
111bdbbd838SJohn Brawn BranchInst::Create(End, If2);
112bdbbd838SJohn Brawn BranchInst::Create(End, Else2);
113bdbbd838SJohn Brawn
11414359ef1SJames Y Knight Value *Val1 = new LoadInst(I32Ty, UndefValue::get(I32PtrTy), "val1", Entry);
11514359ef1SJames Y Knight Value *Val2 = new LoadInst(I32Ty, UndefValue::get(I32PtrTy), "val2", Entry);
11614359ef1SJames Y Knight Value *Val3 = new LoadInst(I32Ty, UndefValue::get(I32PtrTy), "val3", Entry);
11714359ef1SJames Y Knight Value *Val4 = new LoadInst(I32Ty, UndefValue::get(I32PtrTy), "val4", Entry);
118bdbbd838SJohn Brawn
119bdbbd838SJohn Brawn PHINode *Phi1 = PHINode::Create(I32Ty, 2, "phi1", Then);
120bdbbd838SJohn Brawn Phi1->addIncoming(Val1, If1);
121bdbbd838SJohn Brawn Phi1->addIncoming(Val2, Else1);
122bdbbd838SJohn Brawn PHINode *Phi2 = PHINode::Create(I32Ty, 2, "phi2", Then);
123bdbbd838SJohn Brawn Phi2->addIncoming(Val2, If1);
124bdbbd838SJohn Brawn Phi2->addIncoming(Val3, Else1);
125bdbbd838SJohn Brawn PHINode *Phi3 = PHINode::Create(I32Ty, 2, "phi3", End);
126bdbbd838SJohn Brawn Phi3->addIncoming(Phi1, If2);
127bdbbd838SJohn Brawn Phi3->addIncoming(Val3, Else2);
128bdbbd838SJohn Brawn
129bdbbd838SJohn Brawn PhiValues PV(*F);
130bdbbd838SJohn Brawn PhiValues::ValueSet Vals;
131bdbbd838SJohn Brawn
132bdbbd838SJohn Brawn // Check that simple usage works
133bdbbd838SJohn Brawn Vals = PV.getValuesForPhi(Phi1);
134bdbbd838SJohn Brawn EXPECT_EQ(Vals.size(), 2u);
135bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val1));
136bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val2));
137bdbbd838SJohn Brawn Vals = PV.getValuesForPhi(Phi2);
138bdbbd838SJohn Brawn EXPECT_EQ(Vals.size(), 2u);
139bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val2));
140bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val3));
141bdbbd838SJohn Brawn Vals = PV.getValuesForPhi(Phi3);
142bdbbd838SJohn Brawn EXPECT_EQ(Vals.size(), 3u);
143bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val1));
144bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val2));
145bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val3));
146bdbbd838SJohn Brawn
147bdbbd838SJohn Brawn // Check that changing an incoming value in the dependent phi changes the depending phi
148bdbbd838SJohn Brawn Phi1->setIncomingValue(0, Val4);
149bdbbd838SJohn Brawn PV.invalidateValue(Phi1);
150bdbbd838SJohn Brawn Vals = PV.getValuesForPhi(Phi1);
151bdbbd838SJohn Brawn EXPECT_EQ(Vals.size(), 2u);
152bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val4));
153bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val2));
154bdbbd838SJohn Brawn Vals = PV.getValuesForPhi(Phi2);
155bdbbd838SJohn Brawn EXPECT_EQ(Vals.size(), 2u);
156bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val2));
157bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val3));
158bdbbd838SJohn Brawn Vals = PV.getValuesForPhi(Phi3);
159bdbbd838SJohn Brawn EXPECT_EQ(Vals.size(), 3u);
160bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val4));
161bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val2));
162bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val3));
163bdbbd838SJohn Brawn
164bdbbd838SJohn Brawn // Check that replacing an incoming phi with a value works
165bdbbd838SJohn Brawn Phi3->setIncomingValue(0, Val1);
166bdbbd838SJohn Brawn PV.invalidateValue(Phi3);
167bdbbd838SJohn Brawn Vals = PV.getValuesForPhi(Phi1);
168bdbbd838SJohn Brawn EXPECT_EQ(Vals.size(), 2u);
169bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val4));
170bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val2));
171bdbbd838SJohn Brawn Vals = PV.getValuesForPhi(Phi2);
172bdbbd838SJohn Brawn EXPECT_EQ(Vals.size(), 2u);
173bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val2));
174bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val3));
175bdbbd838SJohn Brawn Vals = PV.getValuesForPhi(Phi3);
176bdbbd838SJohn Brawn EXPECT_EQ(Vals.size(), 2u);
177bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val1));
178bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val3));
179bdbbd838SJohn Brawn
180bdbbd838SJohn Brawn // Check that adding a phi as an incoming value works
181bdbbd838SJohn Brawn Phi3->setIncomingValue(1, Phi2);
182bdbbd838SJohn Brawn PV.invalidateValue(Phi3);
183bdbbd838SJohn Brawn Vals = PV.getValuesForPhi(Phi1);
184bdbbd838SJohn Brawn EXPECT_EQ(Vals.size(), 2u);
185bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val4));
186bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val2));
187bdbbd838SJohn Brawn Vals = PV.getValuesForPhi(Phi2);
188bdbbd838SJohn Brawn EXPECT_EQ(Vals.size(), 2u);
189bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val2));
190bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val3));
191bdbbd838SJohn Brawn Vals = PV.getValuesForPhi(Phi3);
192bdbbd838SJohn Brawn EXPECT_EQ(Vals.size(), 3u);
193bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val1));
194bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val2));
195bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val3));
196bdbbd838SJohn Brawn
197bdbbd838SJohn Brawn // Check that replacing an incoming phi then deleting it works
198bdbbd838SJohn Brawn Phi3->setIncomingValue(1, Val2);
199bdbbd838SJohn Brawn PV.invalidateValue(Phi2);
200aa8a88afSJohn Brawn Phi2->eraseFromParent();
201bdbbd838SJohn Brawn PV.invalidateValue(Phi3);
202bdbbd838SJohn Brawn Vals = PV.getValuesForPhi(Phi1);
203bdbbd838SJohn Brawn EXPECT_EQ(Vals.size(), 2u);
204bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val4));
205bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val2));
206bdbbd838SJohn Brawn Vals = PV.getValuesForPhi(Phi3);
207bdbbd838SJohn Brawn EXPECT_EQ(Vals.size(), 2u);
208bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val1));
209bdbbd838SJohn Brawn EXPECT_TRUE(Vals.count(Val2));
210bdbbd838SJohn Brawn }
211