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/ADT/STLExtras.h"
11#include "llvm/ADT/SmallPtrSet.h"
12#include "llvm/IR/Argument.h"
13#include "llvm/IR/Constant.h"
14#include "llvm/IR/Function.h"
15#include "llvm/IR/Instructions.h"
16#include "llvm/IR/IRBuilder.h"
17#include "llvm/IR/LLVMContext.h"
18#include "llvm/Transforms/Utils/Cloning.h"
19#include "gtest/gtest.h"
20
21using namespace llvm;
22
23namespace {
24
25class CloneInstruction : public ::testing::Test {
26protected:
27  virtual void SetUp() {
28    V = NULL;
29  }
30
31  template <typename T>
32  T *clone(T *V1) {
33    Value *V2 = V1->clone();
34    Orig.insert(V1);
35    Clones.insert(V2);
36    return cast<T>(V2);
37  }
38
39  void eraseClones() {
40    DeleteContainerPointers(Clones);
41  }
42
43  virtual void TearDown() {
44    eraseClones();
45    DeleteContainerPointers(Orig);
46    delete V;
47  }
48
49  SmallPtrSet<Value *, 4> Orig;   // Erase on exit
50  SmallPtrSet<Value *, 4> Clones; // Erase in eraseClones
51
52  LLVMContext context;
53  Value *V;
54};
55
56TEST_F(CloneInstruction, OverflowBits) {
57  V = new Argument(Type::getInt32Ty(context));
58
59  BinaryOperator *Add = BinaryOperator::Create(Instruction::Add, V, V);
60  BinaryOperator *Sub = BinaryOperator::Create(Instruction::Sub, V, V);
61  BinaryOperator *Mul = BinaryOperator::Create(Instruction::Mul, V, V);
62
63  BinaryOperator *AddClone = this->clone(Add);
64  BinaryOperator *SubClone = this->clone(Sub);
65  BinaryOperator *MulClone = this->clone(Mul);
66
67  EXPECT_FALSE(AddClone->hasNoUnsignedWrap());
68  EXPECT_FALSE(AddClone->hasNoSignedWrap());
69  EXPECT_FALSE(SubClone->hasNoUnsignedWrap());
70  EXPECT_FALSE(SubClone->hasNoSignedWrap());
71  EXPECT_FALSE(MulClone->hasNoUnsignedWrap());
72  EXPECT_FALSE(MulClone->hasNoSignedWrap());
73
74  eraseClones();
75
76  Add->setHasNoUnsignedWrap();
77  Sub->setHasNoUnsignedWrap();
78  Mul->setHasNoUnsignedWrap();
79
80  AddClone = this->clone(Add);
81  SubClone = this->clone(Sub);
82  MulClone = this->clone(Mul);
83
84  EXPECT_TRUE(AddClone->hasNoUnsignedWrap());
85  EXPECT_FALSE(AddClone->hasNoSignedWrap());
86  EXPECT_TRUE(SubClone->hasNoUnsignedWrap());
87  EXPECT_FALSE(SubClone->hasNoSignedWrap());
88  EXPECT_TRUE(MulClone->hasNoUnsignedWrap());
89  EXPECT_FALSE(MulClone->hasNoSignedWrap());
90
91  eraseClones();
92
93  Add->setHasNoSignedWrap();
94  Sub->setHasNoSignedWrap();
95  Mul->setHasNoSignedWrap();
96
97  AddClone = this->clone(Add);
98  SubClone = this->clone(Sub);
99  MulClone = this->clone(Mul);
100
101  EXPECT_TRUE(AddClone->hasNoUnsignedWrap());
102  EXPECT_TRUE(AddClone->hasNoSignedWrap());
103  EXPECT_TRUE(SubClone->hasNoUnsignedWrap());
104  EXPECT_TRUE(SubClone->hasNoSignedWrap());
105  EXPECT_TRUE(MulClone->hasNoUnsignedWrap());
106  EXPECT_TRUE(MulClone->hasNoSignedWrap());
107
108  eraseClones();
109
110  Add->setHasNoUnsignedWrap(false);
111  Sub->setHasNoUnsignedWrap(false);
112  Mul->setHasNoUnsignedWrap(false);
113
114  AddClone = this->clone(Add);
115  SubClone = this->clone(Sub);
116  MulClone = this->clone(Mul);
117
118  EXPECT_FALSE(AddClone->hasNoUnsignedWrap());
119  EXPECT_TRUE(AddClone->hasNoSignedWrap());
120  EXPECT_FALSE(SubClone->hasNoUnsignedWrap());
121  EXPECT_TRUE(SubClone->hasNoSignedWrap());
122  EXPECT_FALSE(MulClone->hasNoUnsignedWrap());
123  EXPECT_TRUE(MulClone->hasNoSignedWrap());
124}
125
126TEST_F(CloneInstruction, Inbounds) {
127  V = new Argument(Type::getInt32PtrTy(context));
128
129  Constant *Z = Constant::getNullValue(Type::getInt32Ty(context));
130  std::vector<Value *> ops;
131  ops.push_back(Z);
132  GetElementPtrInst *GEP = GetElementPtrInst::Create(V, ops);
133  EXPECT_FALSE(this->clone(GEP)->isInBounds());
134
135  GEP->setIsInBounds();
136  EXPECT_TRUE(this->clone(GEP)->isInBounds());
137}
138
139TEST_F(CloneInstruction, Exact) {
140  V = new Argument(Type::getInt32Ty(context));
141
142  BinaryOperator *SDiv = BinaryOperator::Create(Instruction::SDiv, V, V);
143  EXPECT_FALSE(this->clone(SDiv)->isExact());
144
145  SDiv->setIsExact(true);
146  EXPECT_TRUE(this->clone(SDiv)->isExact());
147}
148
149TEST_F(CloneInstruction, Attributes) {
150  Type *ArgTy1[] = { Type::getInt32PtrTy(context) };
151  FunctionType *FT1 =  FunctionType::get(Type::getVoidTy(context), ArgTy1, false);
152
153  Function *F1 = Function::Create(FT1, Function::ExternalLinkage);
154  BasicBlock *BB = BasicBlock::Create(context, "", F1);
155  IRBuilder<> Builder(BB);
156  Builder.CreateRetVoid();
157
158  Function *F2 = Function::Create(FT1, Function::ExternalLinkage);
159
160  Attribute::AttrKind AK[] = { Attribute::NoCapture };
161  AttributeSet AS = AttributeSet::get(context, 0, AK);
162  Argument *A = F1->arg_begin();
163  A->addAttr(AS);
164
165  SmallVector<ReturnInst*, 4> Returns;
166  ValueToValueMapTy VMap;
167  VMap[A] = UndefValue::get(A->getType());
168
169  CloneFunctionInto(F2, F1, VMap, false, Returns);
170  EXPECT_FALSE(F2->arg_begin()->hasNoCaptureAttr());
171
172  delete F1;
173  delete F2;
174}
175
176}
177