forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			210 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			210 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===- PhiValuesTest.cpp - PhiValues unit tests ---------------------------===//
 | |
| //
 | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | |
| // See https://llvm.org/LICENSE.txt for license information.
 | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "llvm/Analysis/PhiValues.h"
 | |
| #include "llvm/IR/BasicBlock.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);
 | |
| 
 | |
|   // Create a function with phis that do not have other phis as incoming values
 | |
|   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;
 | |
| 
 | |
|   // Check that simple usage works
 | |
|   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));
 | |
| 
 | |
|   // Check that values are updated when one value is replaced with another
 | |
|   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));
 | |
| 
 | |
|   // Check that setting in incoming value directly updates the values
 | |
|   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);
 | |
| 
 | |
|   // Create a function with a phi that has another phi as an incoming value
 | |
|   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;
 | |
| 
 | |
|   // Check that simple usage works
 | |
|   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));
 | |
| 
 | |
|   // Check that changing an incoming value in the dependent phi changes the depending phi
 | |
|   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));
 | |
| 
 | |
|   // Check that replacing an incoming phi with a value works
 | |
|   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));
 | |
| 
 | |
|   // Check that adding a phi as an incoming value works
 | |
|   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));
 | |
| 
 | |
|   // Check that replacing an incoming phi then deleting it works
 | |
|   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));
 | |
| }
 |