#include "llvm/Analysis/PhiValues.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "gtest/gtest.h"
using namespace llvm;
TEST(PhiValuesTest, SimplePhi) {
LLVMContext C;
Module M("PhiValuesTest", C);
Type *VoidTy = Type::getVoidTy(C);
Type *I1Ty = Type::getInt1Ty(C);
Type *I32Ty = Type::getInt32Ty(C);
Type *I32PtrTy = Type::getInt32PtrTy(C);
Function *F = Function::Create(FunctionType::get(VoidTy, false),
Function::ExternalLinkage, "f", M);
BasicBlock *Entry = BasicBlock::Create(C, "entry", F);
BasicBlock *If = BasicBlock::Create(C, "if", F);
BasicBlock *Else = BasicBlock::Create(C, "else", F);
BasicBlock *Then = BasicBlock::Create(C, "then", F);
BranchInst::Create(If, Else, UndefValue::get(I1Ty), Entry);
BranchInst::Create(Then, If);
BranchInst::Create(Then, Else);
Value *Val1 = new LoadInst(I32Ty, UndefValue::get(I32PtrTy), "val1", Entry);
Value *Val2 = new LoadInst(I32Ty, UndefValue::get(I32PtrTy), "val2", Entry);
Value *Val3 = new LoadInst(I32Ty, UndefValue::get(I32PtrTy), "val3", Entry);
Value *Val4 = new LoadInst(I32Ty, UndefValue::get(I32PtrTy), "val4", Entry);
PHINode *Phi1 = PHINode::Create(I32Ty, 2, "phi1", Then);
Phi1->addIncoming(Val1, If);
Phi1->addIncoming(Val2, Else);
PHINode *Phi2 = PHINode::Create(I32Ty, 2, "phi2", Then);
Phi2->addIncoming(Val1, If);
Phi2->addIncoming(Val3, Else);
PhiValues PV(*F);
PhiValues::ValueSet Vals;
Vals = PV.getValuesForPhi(Phi1);
EXPECT_EQ(Vals.size(), 2u);
EXPECT_TRUE(Vals.count(Val1));
EXPECT_TRUE(Vals.count(Val2));
Vals = PV.getValuesForPhi(Phi2);
EXPECT_EQ(Vals.size(), 2u);
EXPECT_TRUE(Vals.count(Val1));
EXPECT_TRUE(Vals.count(Val3));
Val1->replaceAllUsesWith(Val4);
PV.invalidateValue(Val1);
Vals = PV.getValuesForPhi(Phi1);
EXPECT_EQ(Vals.size(), 2u);
EXPECT_TRUE(Vals.count(Val4));
EXPECT_TRUE(Vals.count(Val2));
Vals = PV.getValuesForPhi(Phi2);
EXPECT_EQ(Vals.size(), 2u);
EXPECT_TRUE(Vals.count(Val4));
EXPECT_TRUE(Vals.count(Val3));
Phi1->setIncomingValue(0, Val1);
PV.invalidateValue(Phi1);
Vals = PV.getValuesForPhi(Phi1);
EXPECT_EQ(Vals.size(), 2u);
EXPECT_TRUE(Vals.count(Val1));
EXPECT_TRUE(Vals.count(Val2));
}
TEST(PhiValuesTest, DependentPhi) {
LLVMContext C;
Module M("PhiValuesTest", C);
Type *VoidTy = Type::getVoidTy(C);
Type *I1Ty = Type::getInt1Ty(C);
Type *I32Ty = Type::getInt32Ty(C);
Type *I32PtrTy = Type::getInt32PtrTy(C);
Function *F = Function::Create(FunctionType::get(VoidTy, false),
Function::ExternalLinkage, "f", M);
BasicBlock *Entry = BasicBlock::Create(C, "entry", F);
BasicBlock *If1 = BasicBlock::Create(C, "if1", F);
BasicBlock *Else1 = BasicBlock::Create(C, "else1", F);
BasicBlock *Then = BasicBlock::Create(C, "then", F);
BasicBlock *If2 = BasicBlock::Create(C, "if2", F);
BasicBlock *Else2 = BasicBlock::Create(C, "else2", F);
BasicBlock *End = BasicBlock::Create(C, "then", F);
BranchInst::Create(If1, Else1, UndefValue::get(I1Ty), Entry);
BranchInst::Create(Then, If1);
BranchInst::Create(Then, Else1);
BranchInst::Create(If2, Else2, UndefValue::get(I1Ty), Then);
BranchInst::Create(End, If2);
BranchInst::Create(End, Else2);
Value *Val1 = new LoadInst(I32Ty, UndefValue::get(I32PtrTy), "val1", Entry);
Value *Val2 = new LoadInst(I32Ty, UndefValue::get(I32PtrTy), "val2", Entry);
Value *Val3 = new LoadInst(I32Ty, UndefValue::get(I32PtrTy), "val3", Entry);
Value *Val4 = new LoadInst(I32Ty, UndefValue::get(I32PtrTy), "val4", Entry);
PHINode *Phi1 = PHINode::Create(I32Ty, 2, "phi1", Then);
Phi1->addIncoming(Val1, If1);
Phi1->addIncoming(Val2, Else1);
PHINode *Phi2 = PHINode::Create(I32Ty, 2, "phi2", Then);
Phi2->addIncoming(Val2, If1);
Phi2->addIncoming(Val3, Else1);
PHINode *Phi3 = PHINode::Create(I32Ty, 2, "phi3", End);
Phi3->addIncoming(Phi1, If2);
Phi3->addIncoming(Val3, Else2);
PhiValues PV(*F);
PhiValues::ValueSet Vals;
Vals = PV.getValuesForPhi(Phi1);
EXPECT_EQ(Vals.size(), 2u);
EXPECT_TRUE(Vals.count(Val1));
EXPECT_TRUE(Vals.count(Val2));
Vals = PV.getValuesForPhi(Phi2);
EXPECT_EQ(Vals.size(), 2u);
EXPECT_TRUE(Vals.count(Val2));
EXPECT_TRUE(Vals.count(Val3));
Vals = PV.getValuesForPhi(Phi3);
EXPECT_EQ(Vals.size(), 3u);
EXPECT_TRUE(Vals.count(Val1));
EXPECT_TRUE(Vals.count(Val2));
EXPECT_TRUE(Vals.count(Val3));
Phi1->setIncomingValue(0, Val4);
PV.invalidateValue(Phi1);
Vals = PV.getValuesForPhi(Phi1);
EXPECT_EQ(Vals.size(), 2u);
EXPECT_TRUE(Vals.count(Val4));
EXPECT_TRUE(Vals.count(Val2));
Vals = PV.getValuesForPhi(Phi2);
EXPECT_EQ(Vals.size(), 2u);
EXPECT_TRUE(Vals.count(Val2));
EXPECT_TRUE(Vals.count(Val3));
Vals = PV.getValuesForPhi(Phi3);
EXPECT_EQ(Vals.size(), 3u);
EXPECT_TRUE(Vals.count(Val4));
EXPECT_TRUE(Vals.count(Val2));
EXPECT_TRUE(Vals.count(Val3));
Phi3->setIncomingValue(0, Val1);
PV.invalidateValue(Phi3);
Vals = PV.getValuesForPhi(Phi1);
EXPECT_EQ(Vals.size(), 2u);
EXPECT_TRUE(Vals.count(Val4));
EXPECT_TRUE(Vals.count(Val2));
Vals = PV.getValuesForPhi(Phi2);
EXPECT_EQ(Vals.size(), 2u);
EXPECT_TRUE(Vals.count(Val2));
EXPECT_TRUE(Vals.count(Val3));
Vals = PV.getValuesForPhi(Phi3);
EXPECT_EQ(Vals.size(), 2u);
EXPECT_TRUE(Vals.count(Val1));
EXPECT_TRUE(Vals.count(Val3));
Phi3->setIncomingValue(1, Phi2);
PV.invalidateValue(Phi3);
Vals = PV.getValuesForPhi(Phi1);
EXPECT_EQ(Vals.size(), 2u);
EXPECT_TRUE(Vals.count(Val4));
EXPECT_TRUE(Vals.count(Val2));
Vals = PV.getValuesForPhi(Phi2);
EXPECT_EQ(Vals.size(), 2u);
EXPECT_TRUE(Vals.count(Val2));
EXPECT_TRUE(Vals.count(Val3));
Vals = PV.getValuesForPhi(Phi3);
EXPECT_EQ(Vals.size(), 3u);
EXPECT_TRUE(Vals.count(Val1));
EXPECT_TRUE(Vals.count(Val2));
EXPECT_TRUE(Vals.count(Val3));
Phi3->setIncomingValue(1, Val2);
PV.invalidateValue(Phi2);
Phi2->eraseFromParent();
PV.invalidateValue(Phi3);
Vals = PV.getValuesForPhi(Phi1);
EXPECT_EQ(Vals.size(), 2u);
EXPECT_TRUE(Vals.count(Val4));
EXPECT_TRUE(Vals.count(Val2));
Vals = PV.getValuesForPhi(Phi3);
EXPECT_EQ(Vals.size(), 2u);
EXPECT_TRUE(Vals.count(Val1));
EXPECT_TRUE(Vals.count(Val2));
}