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
18using namespace llvm;
19
20namespace {
21
22
23TEST(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
53TEST(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
83TEST(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
113TEST(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
144TEST(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
174TEST(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
204TEST(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
234TEST(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