Home | History | Annotate | Download | only in Utils
      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 
     28 using namespace llvm;
     29 
     30 namespace {
     31 
     32 class CloneInstruction : public ::testing::Test {
     33 protected:
     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 
     63 TEST_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 
    133 TEST_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 
    146 TEST_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 
    156 TEST_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 
    183 TEST_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 
    206 class CloneFunc : public ::testing::Test {
    207 protected:
    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     DIArray ParamTypes = DBuilder.getOrCreateArray(ArrayRef<Value*>());
    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     DIVariable Variable = DBuilder.createLocalVariable(
    259       dwarf::DW_TAG_auto_variable, Subprogram, "x", File, 5, IntType, true);
    260     DBuilder.insertDeclare(Alloca, Variable, Store);
    261     DBuilder.insertDbgValueIntrinsic(AllocaContent, 0, Variable, Terminator);
    262     // Finalize the debug info
    263     DBuilder.finalize();
    264 
    265 
    266     // Create another, empty, compile unit
    267     DIBuilder DBuilder2(*M);
    268     DBuilder2.createCompileUnit(dwarf::DW_LANG_C99,
    269         "extra.c", "/file/dir", "CloneFunc", false, "", 0);
    270     DBuilder2.finalize();
    271   }
    272 
    273   void CreateNewFunc() {
    274     ValueToValueMapTy VMap;
    275     NewFunc = CloneFunction(OldFunc, VMap, true, nullptr);
    276     M->getFunctionList().push_back(NewFunc);
    277   }
    278 
    279   void SetupFinder() {
    280     Finder = new DebugInfoFinder();
    281     Finder->processModule(*M);
    282   }
    283 
    284   LLVMContext C;
    285   Function* OldFunc;
    286   Function* NewFunc;
    287   Module* M;
    288   DebugInfoFinder* Finder;
    289 };
    290 
    291 // Test that a new, distinct function was created.
    292 TEST_F(CloneFunc, NewFunctionCreated) {
    293   EXPECT_NE(OldFunc, NewFunc);
    294 }
    295 
    296 // Test that a new subprogram entry was added and is pointing to the new
    297 // function, while the original subprogram still points to the old one.
    298 TEST_F(CloneFunc, Subprogram) {
    299   unsigned SubprogramCount = Finder->subprogram_count();
    300   EXPECT_EQ(2U, SubprogramCount);
    301 
    302   auto Iter = Finder->subprograms().begin();
    303   DISubprogram Sub1(*Iter);
    304   EXPECT_TRUE(Sub1.Verify());
    305   Iter++;
    306   DISubprogram Sub2(*Iter);
    307   EXPECT_TRUE(Sub2.Verify());
    308 
    309   EXPECT_TRUE((Sub1.getFunction() == OldFunc && Sub2.getFunction() == NewFunc)
    310            || (Sub1.getFunction() == NewFunc && Sub2.getFunction() == OldFunc));
    311 }
    312 
    313 // Test that the new subprogram entry was not added to the CU which doesn't
    314 // contain the old subprogram entry.
    315 TEST_F(CloneFunc, SubprogramInRightCU) {
    316   EXPECT_EQ(2U, Finder->compile_unit_count());
    317 
    318   auto Iter = Finder->compile_units().begin();
    319   DICompileUnit CU1(*Iter);
    320   EXPECT_TRUE(CU1.Verify());
    321   Iter++;
    322   DICompileUnit CU2(*Iter);
    323   EXPECT_TRUE(CU2.Verify());
    324   EXPECT_TRUE(CU1.getSubprograms().getNumElements() == 0
    325            || CU2.getSubprograms().getNumElements() == 0);
    326 }
    327 
    328 // Test that instructions in the old function still belong to it in the
    329 // metadata, while instruction in the new function belong to the new one.
    330 TEST_F(CloneFunc, InstructionOwnership) {
    331   inst_iterator OldIter = inst_begin(OldFunc);
    332   inst_iterator OldEnd = inst_end(OldFunc);
    333   inst_iterator NewIter = inst_begin(NewFunc);
    334   inst_iterator NewEnd = inst_end(NewFunc);
    335   while (OldIter != OldEnd && NewIter != NewEnd) {
    336     Instruction& OldI = *OldIter;
    337     Instruction& NewI = *NewIter;
    338     EXPECT_NE(&OldI, &NewI);
    339 
    340     EXPECT_EQ(OldI.hasMetadata(), NewI.hasMetadata());
    341     if (OldI.hasMetadata()) {
    342       const DebugLoc& OldDL = OldI.getDebugLoc();
    343       const DebugLoc& NewDL = NewI.getDebugLoc();
    344 
    345       // Verify that the debug location data is the same
    346       EXPECT_EQ(OldDL.getLine(), NewDL.getLine());
    347       EXPECT_EQ(OldDL.getCol(), NewDL.getCol());
    348 
    349       // But that they belong to different functions
    350       DISubprogram OldSubprogram(OldDL.getScope(C));
    351       DISubprogram NewSubprogram(NewDL.getScope(C));
    352       EXPECT_TRUE(OldSubprogram.Verify());
    353       EXPECT_TRUE(NewSubprogram.Verify());
    354       EXPECT_EQ(OldFunc, OldSubprogram.getFunction());
    355       EXPECT_EQ(NewFunc, NewSubprogram.getFunction());
    356     }
    357 
    358     ++OldIter;
    359     ++NewIter;
    360   }
    361   EXPECT_EQ(OldEnd, OldIter);
    362   EXPECT_EQ(NewEnd, NewIter);
    363 }
    364 
    365 // Test that the arguments for debug intrinsics in the new function were
    366 // properly cloned
    367 TEST_F(CloneFunc, DebugIntrinsics) {
    368   inst_iterator OldIter = inst_begin(OldFunc);
    369   inst_iterator OldEnd = inst_end(OldFunc);
    370   inst_iterator NewIter = inst_begin(NewFunc);
    371   inst_iterator NewEnd = inst_end(NewFunc);
    372   while (OldIter != OldEnd && NewIter != NewEnd) {
    373     Instruction& OldI = *OldIter;
    374     Instruction& NewI = *NewIter;
    375     if (DbgDeclareInst* OldIntrin = dyn_cast<DbgDeclareInst>(&OldI)) {
    376       DbgDeclareInst* NewIntrin = dyn_cast<DbgDeclareInst>(&NewI);
    377       EXPECT_TRUE(NewIntrin);
    378 
    379       // Old address must belong to the old function
    380       EXPECT_EQ(OldFunc, cast<AllocaInst>(OldIntrin->getAddress())->
    381                          getParent()->getParent());
    382       // New address must belong to the new function
    383       EXPECT_EQ(NewFunc, cast<AllocaInst>(NewIntrin->getAddress())->
    384                          getParent()->getParent());
    385 
    386       // Old variable must belong to the old function
    387       EXPECT_EQ(OldFunc, DISubprogram(DIVariable(OldIntrin->getVariable())
    388                          .getContext()).getFunction());
    389       // New variable must belong to the New function
    390       EXPECT_EQ(NewFunc, DISubprogram(DIVariable(NewIntrin->getVariable())
    391                          .getContext()).getFunction());
    392     } else if (DbgValueInst* OldIntrin = dyn_cast<DbgValueInst>(&OldI)) {
    393       DbgValueInst* NewIntrin = dyn_cast<DbgValueInst>(&NewI);
    394       EXPECT_TRUE(NewIntrin);
    395 
    396       // Old variable must belong to the old function
    397       EXPECT_EQ(OldFunc, DISubprogram(DIVariable(OldIntrin->getVariable())
    398                          .getContext()).getFunction());
    399       // New variable must belong to the New function
    400       EXPECT_EQ(NewFunc, DISubprogram(DIVariable(NewIntrin->getVariable())
    401                          .getContext()).getFunction());
    402     }
    403 
    404     ++OldIter;
    405     ++NewIter;
    406   }
    407 }
    408 
    409 }
    410