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