brintos

brintos / llvm-project-archived public Read only

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