Cloning.cpp revision 37ed9c199ca639565f6ce88105f9e39e898d82d0
1//===- Cloning.cpp - Unit tests for the Cloner ----------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "llvm/Transforms/Utils/Cloning.h" 11#include "llvm/ADT/ArrayRef.h" 12#include "llvm/ADT/STLExtras.h" 13#include "llvm/ADT/SmallPtrSet.h" 14#include "llvm/IR/Argument.h" 15#include "llvm/IR/Constant.h" 16#include "llvm/IR/DebugInfo.h" 17#include "llvm/IR/DIBuilder.h" 18#include "llvm/IR/Function.h" 19#include "llvm/IR/IRBuilder.h" 20#include "llvm/IR/InstIterator.h" 21#include "llvm/IR/Instructions.h" 22#include "llvm/IR/IntrinsicInst.h" 23#include "llvm/IR/IRBuilder.h" 24#include "llvm/IR/Module.h" 25#include "llvm/IR/LLVMContext.h" 26#include "gtest/gtest.h" 27 28using namespace llvm; 29 30namespace { 31 32class CloneInstruction : public ::testing::Test { 33protected: 34 virtual void SetUp() { 35 V = nullptr; 36 } 37 38 template <typename T> 39 T *clone(T *V1) { 40 Value *V2 = V1->clone(); 41 Orig.insert(V1); 42 Clones.insert(V2); 43 return cast<T>(V2); 44 } 45 46 void eraseClones() { 47 DeleteContainerPointers(Clones); 48 } 49 50 virtual void TearDown() { 51 eraseClones(); 52 DeleteContainerPointers(Orig); 53 delete V; 54 } 55 56 SmallPtrSet<Value *, 4> Orig; // Erase on exit 57 SmallPtrSet<Value *, 4> Clones; // Erase in eraseClones 58 59 LLVMContext context; 60 Value *V; 61}; 62 63TEST_F(CloneInstruction, OverflowBits) { 64 V = new Argument(Type::getInt32Ty(context)); 65 66 BinaryOperator *Add = BinaryOperator::Create(Instruction::Add, V, V); 67 BinaryOperator *Sub = BinaryOperator::Create(Instruction::Sub, V, V); 68 BinaryOperator *Mul = BinaryOperator::Create(Instruction::Mul, V, V); 69 70 BinaryOperator *AddClone = this->clone(Add); 71 BinaryOperator *SubClone = this->clone(Sub); 72 BinaryOperator *MulClone = this->clone(Mul); 73 74 EXPECT_FALSE(AddClone->hasNoUnsignedWrap()); 75 EXPECT_FALSE(AddClone->hasNoSignedWrap()); 76 EXPECT_FALSE(SubClone->hasNoUnsignedWrap()); 77 EXPECT_FALSE(SubClone->hasNoSignedWrap()); 78 EXPECT_FALSE(MulClone->hasNoUnsignedWrap()); 79 EXPECT_FALSE(MulClone->hasNoSignedWrap()); 80 81 eraseClones(); 82 83 Add->setHasNoUnsignedWrap(); 84 Sub->setHasNoUnsignedWrap(); 85 Mul->setHasNoUnsignedWrap(); 86 87 AddClone = this->clone(Add); 88 SubClone = this->clone(Sub); 89 MulClone = this->clone(Mul); 90 91 EXPECT_TRUE(AddClone->hasNoUnsignedWrap()); 92 EXPECT_FALSE(AddClone->hasNoSignedWrap()); 93 EXPECT_TRUE(SubClone->hasNoUnsignedWrap()); 94 EXPECT_FALSE(SubClone->hasNoSignedWrap()); 95 EXPECT_TRUE(MulClone->hasNoUnsignedWrap()); 96 EXPECT_FALSE(MulClone->hasNoSignedWrap()); 97 98 eraseClones(); 99 100 Add->setHasNoSignedWrap(); 101 Sub->setHasNoSignedWrap(); 102 Mul->setHasNoSignedWrap(); 103 104 AddClone = this->clone(Add); 105 SubClone = this->clone(Sub); 106 MulClone = this->clone(Mul); 107 108 EXPECT_TRUE(AddClone->hasNoUnsignedWrap()); 109 EXPECT_TRUE(AddClone->hasNoSignedWrap()); 110 EXPECT_TRUE(SubClone->hasNoUnsignedWrap()); 111 EXPECT_TRUE(SubClone->hasNoSignedWrap()); 112 EXPECT_TRUE(MulClone->hasNoUnsignedWrap()); 113 EXPECT_TRUE(MulClone->hasNoSignedWrap()); 114 115 eraseClones(); 116 117 Add->setHasNoUnsignedWrap(false); 118 Sub->setHasNoUnsignedWrap(false); 119 Mul->setHasNoUnsignedWrap(false); 120 121 AddClone = this->clone(Add); 122 SubClone = this->clone(Sub); 123 MulClone = this->clone(Mul); 124 125 EXPECT_FALSE(AddClone->hasNoUnsignedWrap()); 126 EXPECT_TRUE(AddClone->hasNoSignedWrap()); 127 EXPECT_FALSE(SubClone->hasNoUnsignedWrap()); 128 EXPECT_TRUE(SubClone->hasNoSignedWrap()); 129 EXPECT_FALSE(MulClone->hasNoUnsignedWrap()); 130 EXPECT_TRUE(MulClone->hasNoSignedWrap()); 131} 132 133TEST_F(CloneInstruction, Inbounds) { 134 V = new Argument(Type::getInt32PtrTy(context)); 135 136 Constant *Z = Constant::getNullValue(Type::getInt32Ty(context)); 137 std::vector<Value *> ops; 138 ops.push_back(Z); 139 GetElementPtrInst *GEP = GetElementPtrInst::Create(V, ops); 140 EXPECT_FALSE(this->clone(GEP)->isInBounds()); 141 142 GEP->setIsInBounds(); 143 EXPECT_TRUE(this->clone(GEP)->isInBounds()); 144} 145 146TEST_F(CloneInstruction, Exact) { 147 V = new Argument(Type::getInt32Ty(context)); 148 149 BinaryOperator *SDiv = BinaryOperator::Create(Instruction::SDiv, V, V); 150 EXPECT_FALSE(this->clone(SDiv)->isExact()); 151 152 SDiv->setIsExact(true); 153 EXPECT_TRUE(this->clone(SDiv)->isExact()); 154} 155 156TEST_F(CloneInstruction, Attributes) { 157 Type *ArgTy1[] = { Type::getInt32PtrTy(context) }; 158 FunctionType *FT1 = FunctionType::get(Type::getVoidTy(context), ArgTy1, false); 159 160 Function *F1 = Function::Create(FT1, Function::ExternalLinkage); 161 BasicBlock *BB = BasicBlock::Create(context, "", F1); 162 IRBuilder<> Builder(BB); 163 Builder.CreateRetVoid(); 164 165 Function *F2 = Function::Create(FT1, Function::ExternalLinkage); 166 167 Attribute::AttrKind AK[] = { Attribute::NoCapture }; 168 AttributeSet AS = AttributeSet::get(context, 0, AK); 169 Argument *A = F1->arg_begin(); 170 A->addAttr(AS); 171 172 SmallVector<ReturnInst*, 4> Returns; 173 ValueToValueMapTy VMap; 174 VMap[A] = UndefValue::get(A->getType()); 175 176 CloneFunctionInto(F2, F1, VMap, false, Returns); 177 EXPECT_FALSE(F2->arg_begin()->hasNoCaptureAttr()); 178 179 delete F1; 180 delete F2; 181} 182 183TEST_F(CloneInstruction, CallingConvention) { 184 Type *ArgTy1[] = { Type::getInt32PtrTy(context) }; 185 FunctionType *FT1 = FunctionType::get(Type::getVoidTy(context), ArgTy1, false); 186 187 Function *F1 = Function::Create(FT1, Function::ExternalLinkage); 188 F1->setCallingConv(CallingConv::Cold); 189 BasicBlock *BB = BasicBlock::Create(context, "", F1); 190 IRBuilder<> Builder(BB); 191 Builder.CreateRetVoid(); 192 193 Function *F2 = Function::Create(FT1, Function::ExternalLinkage); 194 195 SmallVector<ReturnInst*, 4> Returns; 196 ValueToValueMapTy VMap; 197 VMap[F1->arg_begin()] = F2->arg_begin(); 198 199 CloneFunctionInto(F2, F1, VMap, false, Returns); 200 EXPECT_EQ(CallingConv::Cold, F2->getCallingConv()); 201 202 delete F1; 203 delete F2; 204} 205 206class CloneFunc : public ::testing::Test { 207protected: 208 virtual void SetUp() { 209 SetupModule(); 210 CreateOldFunc(); 211 CreateNewFunc(); 212 SetupFinder(); 213 } 214 215 virtual void TearDown() { 216 delete Finder; 217 } 218 219 void SetupModule() { 220 M = new Module("", C); 221 } 222 223 void CreateOldFunc() { 224 FunctionType* FuncType = FunctionType::get(Type::getVoidTy(C), false); 225 OldFunc = Function::Create(FuncType, GlobalValue::PrivateLinkage, "f", M); 226 CreateOldFunctionBodyAndDI(); 227 } 228 229 void CreateOldFunctionBodyAndDI() { 230 DIBuilder DBuilder(*M); 231 IRBuilder<> IBuilder(C); 232 233 // Function DI 234 DIFile File = DBuilder.createFile("filename.c", "/file/dir/"); 235 DITypeArray ParamTypes = DBuilder.getOrCreateTypeArray(None); 236 DICompositeType FuncType = DBuilder.createSubroutineType(File, ParamTypes); 237 DICompileUnit CU = DBuilder.createCompileUnit(dwarf::DW_LANG_C99, 238 "filename.c", "/file/dir", "CloneFunc", false, "", 0); 239 240 DISubprogram Subprogram = DBuilder.createFunction(CU, "f", "f", File, 4, 241 FuncType, true, true, 3, 0, false, OldFunc); 242 243 // Function body 244 BasicBlock* Entry = BasicBlock::Create(C, "", OldFunc); 245 IBuilder.SetInsertPoint(Entry); 246 DebugLoc Loc = DebugLoc::get(3, 2, Subprogram); 247 IBuilder.SetCurrentDebugLocation(Loc); 248 AllocaInst* Alloca = IBuilder.CreateAlloca(IntegerType::getInt32Ty(C)); 249 IBuilder.SetCurrentDebugLocation(DebugLoc::get(4, 2, Subprogram)); 250 Value* AllocaContent = IBuilder.getInt32(1); 251 Instruction* Store = IBuilder.CreateStore(AllocaContent, Alloca); 252 IBuilder.SetCurrentDebugLocation(DebugLoc::get(5, 2, Subprogram)); 253 Instruction* Terminator = IBuilder.CreateRetVoid(); 254 255 // Create a local variable around the alloca 256 DIType IntType = DBuilder.createBasicType("int", 32, 0, 257 dwarf::DW_ATE_signed); 258 DIExpression E = DBuilder.createExpression(); 259 DIVariable Variable = DBuilder.createLocalVariable( 260 dwarf::DW_TAG_auto_variable, Subprogram, "x", File, 5, IntType, true); 261 DBuilder.insertDeclare(Alloca, Variable, E, Store); 262 DBuilder.insertDbgValueIntrinsic(AllocaContent, 0, Variable, E, Terminator); 263 // Finalize the debug info 264 DBuilder.finalize(); 265 266 267 // Create another, empty, compile unit 268 DIBuilder DBuilder2(*M); 269 DBuilder2.createCompileUnit(dwarf::DW_LANG_C99, 270 "extra.c", "/file/dir", "CloneFunc", false, "", 0); 271 DBuilder2.finalize(); 272 } 273 274 void CreateNewFunc() { 275 ValueToValueMapTy VMap; 276 NewFunc = CloneFunction(OldFunc, VMap, true, nullptr); 277 M->getFunctionList().push_back(NewFunc); 278 } 279 280 void SetupFinder() { 281 Finder = new DebugInfoFinder(); 282 Finder->processModule(*M); 283 } 284 285 LLVMContext C; 286 Function* OldFunc; 287 Function* NewFunc; 288 Module* M; 289 DebugInfoFinder* Finder; 290}; 291 292// Test that a new, distinct function was created. 293TEST_F(CloneFunc, NewFunctionCreated) { 294 EXPECT_NE(OldFunc, NewFunc); 295} 296 297// Test that a new subprogram entry was added and is pointing to the new 298// function, while the original subprogram still points to the old one. 299TEST_F(CloneFunc, Subprogram) { 300 unsigned SubprogramCount = Finder->subprogram_count(); 301 EXPECT_EQ(2U, SubprogramCount); 302 303 auto Iter = Finder->subprograms().begin(); 304 DISubprogram Sub1(*Iter); 305 EXPECT_TRUE(Sub1.Verify()); 306 Iter++; 307 DISubprogram Sub2(*Iter); 308 EXPECT_TRUE(Sub2.Verify()); 309 310 EXPECT_TRUE((Sub1.getFunction() == OldFunc && Sub2.getFunction() == NewFunc) 311 || (Sub1.getFunction() == NewFunc && Sub2.getFunction() == OldFunc)); 312} 313 314// Test that the new subprogram entry was not added to the CU which doesn't 315// contain the old subprogram entry. 316TEST_F(CloneFunc, SubprogramInRightCU) { 317 EXPECT_EQ(2U, Finder->compile_unit_count()); 318 319 auto Iter = Finder->compile_units().begin(); 320 DICompileUnit CU1(*Iter); 321 EXPECT_TRUE(CU1.Verify()); 322 Iter++; 323 DICompileUnit CU2(*Iter); 324 EXPECT_TRUE(CU2.Verify()); 325 EXPECT_TRUE(CU1.getSubprograms().getNumElements() == 0 326 || CU2.getSubprograms().getNumElements() == 0); 327} 328 329// Test that instructions in the old function still belong to it in the 330// metadata, while instruction in the new function belong to the new one. 331TEST_F(CloneFunc, InstructionOwnership) { 332 inst_iterator OldIter = inst_begin(OldFunc); 333 inst_iterator OldEnd = inst_end(OldFunc); 334 inst_iterator NewIter = inst_begin(NewFunc); 335 inst_iterator NewEnd = inst_end(NewFunc); 336 while (OldIter != OldEnd && NewIter != NewEnd) { 337 Instruction& OldI = *OldIter; 338 Instruction& NewI = *NewIter; 339 EXPECT_NE(&OldI, &NewI); 340 341 EXPECT_EQ(OldI.hasMetadata(), NewI.hasMetadata()); 342 if (OldI.hasMetadata()) { 343 const DebugLoc& OldDL = OldI.getDebugLoc(); 344 const DebugLoc& NewDL = NewI.getDebugLoc(); 345 346 // Verify that the debug location data is the same 347 EXPECT_EQ(OldDL.getLine(), NewDL.getLine()); 348 EXPECT_EQ(OldDL.getCol(), NewDL.getCol()); 349 350 // But that they belong to different functions 351 DISubprogram OldSubprogram(OldDL.getScope(C)); 352 DISubprogram NewSubprogram(NewDL.getScope(C)); 353 EXPECT_TRUE(OldSubprogram.Verify()); 354 EXPECT_TRUE(NewSubprogram.Verify()); 355 EXPECT_EQ(OldFunc, OldSubprogram.getFunction()); 356 EXPECT_EQ(NewFunc, NewSubprogram.getFunction()); 357 } 358 359 ++OldIter; 360 ++NewIter; 361 } 362 EXPECT_EQ(OldEnd, OldIter); 363 EXPECT_EQ(NewEnd, NewIter); 364} 365 366// Test that the arguments for debug intrinsics in the new function were 367// properly cloned 368TEST_F(CloneFunc, DebugIntrinsics) { 369 inst_iterator OldIter = inst_begin(OldFunc); 370 inst_iterator OldEnd = inst_end(OldFunc); 371 inst_iterator NewIter = inst_begin(NewFunc); 372 inst_iterator NewEnd = inst_end(NewFunc); 373 while (OldIter != OldEnd && NewIter != NewEnd) { 374 Instruction& OldI = *OldIter; 375 Instruction& NewI = *NewIter; 376 if (DbgDeclareInst* OldIntrin = dyn_cast<DbgDeclareInst>(&OldI)) { 377 DbgDeclareInst* NewIntrin = dyn_cast<DbgDeclareInst>(&NewI); 378 EXPECT_TRUE(NewIntrin); 379 380 // Old address must belong to the old function 381 EXPECT_EQ(OldFunc, cast<AllocaInst>(OldIntrin->getAddress())-> 382 getParent()->getParent()); 383 // New address must belong to the new function 384 EXPECT_EQ(NewFunc, cast<AllocaInst>(NewIntrin->getAddress())-> 385 getParent()->getParent()); 386 387 // Old variable must belong to the old function 388 EXPECT_EQ(OldFunc, DISubprogram(DIVariable(OldIntrin->getVariable()) 389 .getContext()).getFunction()); 390 // New variable must belong to the New function 391 EXPECT_EQ(NewFunc, DISubprogram(DIVariable(NewIntrin->getVariable()) 392 .getContext()).getFunction()); 393 } else if (DbgValueInst* OldIntrin = dyn_cast<DbgValueInst>(&OldI)) { 394 DbgValueInst* NewIntrin = dyn_cast<DbgValueInst>(&NewI); 395 EXPECT_TRUE(NewIntrin); 396 397 // Old variable must belong to the old function 398 EXPECT_EQ(OldFunc, DISubprogram(DIVariable(OldIntrin->getVariable()) 399 .getContext()).getFunction()); 400 // New variable must belong to the New function 401 EXPECT_EQ(NewFunc, DISubprogram(DIVariable(NewIntrin->getVariable()) 402 .getContext()).getFunction()); 403 } 404 405 ++OldIter; 406 ++NewIter; 407 } 408} 409 410} 411