1 //===- IntegerDivision.cpp - Unit tests for the integer division code -----===//
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/IntegerDivision.h"
11 #include "llvm/IR/BasicBlock.h"
12 #include "llvm/IR/Function.h"
13 #include "llvm/IR/GlobalValue.h"
14 #include "llvm/IR/IRBuilder.h"
15 #include "llvm/IR/Module.h"
16 #include "gtest/gtest.h"
17
18 using namespace llvm;
19
20 namespace {
21
22
TEST(IntegerDivision,SDiv)23 TEST(IntegerDivision, SDiv) {
24 LLVMContext &C(getGlobalContext());
25 Module M("test division", C);
26 IRBuilder<> Builder(C);
27
28 SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
29 Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
30 ArgTys, false),
31 GlobalValue::ExternalLinkage, "F", &M);
32 assert(F->getArgumentList().size() == 2);
33
34 BasicBlock *BB = BasicBlock::Create(C, "", F);
35 Builder.SetInsertPoint(BB);
36
37 Function::arg_iterator AI = F->arg_begin();
38 Value *A = AI++;
39 Value *B = AI++;
40
41 Value *Div = Builder.CreateSDiv(A, B);
42 EXPECT_TRUE(BB->front().getOpcode() == Instruction::SDiv);
43
44 Value *Ret = Builder.CreateRet(Div);
45
46 expandDivision(cast<BinaryOperator>(Div));
47 EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr);
48
49 Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
50 EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::Sub);
51 }
52
TEST(IntegerDivision,UDiv)53 TEST(IntegerDivision, UDiv) {
54 LLVMContext &C(getGlobalContext());
55 Module M("test division", C);
56 IRBuilder<> Builder(C);
57
58 SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
59 Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
60 ArgTys, false),
61 GlobalValue::ExternalLinkage, "F", &M);
62 assert(F->getArgumentList().size() == 2);
63
64 BasicBlock *BB = BasicBlock::Create(C, "", F);
65 Builder.SetInsertPoint(BB);
66
67 Function::arg_iterator AI = F->arg_begin();
68 Value *A = AI++;
69 Value *B = AI++;
70
71 Value *Div = Builder.CreateUDiv(A, B);
72 EXPECT_TRUE(BB->front().getOpcode() == Instruction::UDiv);
73
74 Value *Ret = Builder.CreateRet(Div);
75
76 expandDivision(cast<BinaryOperator>(Div));
77 EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp);
78
79 Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
80 EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::PHI);
81 }
82
TEST(IntegerDivision,SRem)83 TEST(IntegerDivision, SRem) {
84 LLVMContext &C(getGlobalContext());
85 Module M("test remainder", C);
86 IRBuilder<> Builder(C);
87
88 SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
89 Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
90 ArgTys, false),
91 GlobalValue::ExternalLinkage, "F", &M);
92 assert(F->getArgumentList().size() == 2);
93
94 BasicBlock *BB = BasicBlock::Create(C, "", F);
95 Builder.SetInsertPoint(BB);
96
97 Function::arg_iterator AI = F->arg_begin();
98 Value *A = AI++;
99 Value *B = AI++;
100
101 Value *Rem = Builder.CreateSRem(A, B);
102 EXPECT_TRUE(BB->front().getOpcode() == Instruction::SRem);
103
104 Value *Ret = Builder.CreateRet(Rem);
105
106 expandRemainder(cast<BinaryOperator>(Rem));
107 EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr);
108
109 Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
110 EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
111 }
112
TEST(IntegerDivision,URem)113 TEST(IntegerDivision, URem) {
114 LLVMContext &C(getGlobalContext());
115 Module M("test remainder", C);
116 IRBuilder<> Builder(C);
117
118 SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
119 Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
120 ArgTys, false),
121 GlobalValue::ExternalLinkage, "F", &M);
122 assert(F->getArgumentList().size() == 2);
123
124 BasicBlock *BB = BasicBlock::Create(C, "", F);
125 Builder.SetInsertPoint(BB);
126
127 Function::arg_iterator AI = F->arg_begin();
128 Value *A = AI++;
129 Value *B = AI++;
130
131 Value *Rem = Builder.CreateURem(A, B);
132 EXPECT_TRUE(BB->front().getOpcode() == Instruction::URem);
133
134 Value *Ret = Builder.CreateRet(Rem);
135
136 expandRemainder(cast<BinaryOperator>(Rem));
137 EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp);
138
139 Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
140 EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
141 }
142
143
TEST(IntegerDivision,SDiv64)144 TEST(IntegerDivision, SDiv64) {
145 LLVMContext &C(getGlobalContext());
146 Module M("test division", C);
147 IRBuilder<> Builder(C);
148
149 SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty());
150 Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
151 ArgTys, false),
152 GlobalValue::ExternalLinkage, "F", &M);
153 assert(F->getArgumentList().size() == 2);
154
155 BasicBlock *BB = BasicBlock::Create(C, "", F);
156 Builder.SetInsertPoint(BB);
157
158 Function::arg_iterator AI = F->arg_begin();
159 Value *A = AI++;
160 Value *B = AI++;
161
162 Value *Div = Builder.CreateSDiv(A, B);
163 EXPECT_TRUE(BB->front().getOpcode() == Instruction::SDiv);
164
165 Value *Ret = Builder.CreateRet(Div);
166
167 expandDivision(cast<BinaryOperator>(Div));
168 EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr);
169
170 Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
171 EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::Sub);
172 }
173
TEST(IntegerDivision,UDiv64)174 TEST(IntegerDivision, UDiv64) {
175 LLVMContext &C(getGlobalContext());
176 Module M("test division", C);
177 IRBuilder<> Builder(C);
178
179 SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty());
180 Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
181 ArgTys, false),
182 GlobalValue::ExternalLinkage, "F", &M);
183 assert(F->getArgumentList().size() == 2);
184
185 BasicBlock *BB = BasicBlock::Create(C, "", F);
186 Builder.SetInsertPoint(BB);
187
188 Function::arg_iterator AI = F->arg_begin();
189 Value *A = AI++;
190 Value *B = AI++;
191
192 Value *Div = Builder.CreateUDiv(A, B);
193 EXPECT_TRUE(BB->front().getOpcode() == Instruction::UDiv);
194
195 Value *Ret = Builder.CreateRet(Div);
196
197 expandDivision(cast<BinaryOperator>(Div));
198 EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp);
199
200 Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
201 EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::PHI);
202 }
203
TEST(IntegerDivision,SRem64)204 TEST(IntegerDivision, SRem64) {
205 LLVMContext &C(getGlobalContext());
206 Module M("test remainder", C);
207 IRBuilder<> Builder(C);
208
209 SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty());
210 Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
211 ArgTys, false),
212 GlobalValue::ExternalLinkage, "F", &M);
213 assert(F->getArgumentList().size() == 2);
214
215 BasicBlock *BB = BasicBlock::Create(C, "", F);
216 Builder.SetInsertPoint(BB);
217
218 Function::arg_iterator AI = F->arg_begin();
219 Value *A = AI++;
220 Value *B = AI++;
221
222 Value *Rem = Builder.CreateSRem(A, B);
223 EXPECT_TRUE(BB->front().getOpcode() == Instruction::SRem);
224
225 Value *Ret = Builder.CreateRet(Rem);
226
227 expandRemainder(cast<BinaryOperator>(Rem));
228 EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr);
229
230 Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
231 EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
232 }
233
TEST(IntegerDivision,URem64)234 TEST(IntegerDivision, URem64) {
235 LLVMContext &C(getGlobalContext());
236 Module M("test remainder", C);
237 IRBuilder<> Builder(C);
238
239 SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty());
240 Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
241 ArgTys, false),
242 GlobalValue::ExternalLinkage, "F", &M);
243 assert(F->getArgumentList().size() == 2);
244
245 BasicBlock *BB = BasicBlock::Create(C, "", F);
246 Builder.SetInsertPoint(BB);
247
248 Function::arg_iterator AI = F->arg_begin();
249 Value *A = AI++;
250 Value *B = AI++;
251
252 Value *Rem = Builder.CreateURem(A, B);
253 EXPECT_TRUE(BB->front().getOpcode() == Instruction::URem);
254
255 Value *Ret = Builder.CreateRet(Rem);
256
257 expandRemainder(cast<BinaryOperator>(Rem));
258 EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp);
259
260 Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
261 EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
262 }
263
264 }
265