[llvm] [cmake] Add possibility to use ChooseMSVCCRT.cmake when include LLVM library
[llvm-core.git] / unittests / Analysis / PhiValuesTest.cpp
blob82c02337ef2c9cb8e8e16ab90a7755b2368ffffa
1 //===- PhiValuesTest.cpp - PhiValues unit tests ---------------------------===//
2 //
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
6 //
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"
17 using namespace llvm;
19 TEST(PhiValuesTest, SimplePhi) {
20 LLVMContext C;
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);
52 PhiValues PV(*F);
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) {
87 LLVMContext C;
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);
128 PhiValues PV(*F);
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));