1 //===- IntegerDivision.cpp - Unit tests for the integer division code -----===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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"
23 TEST(IntegerDivision, SDiv) {
24 LLVMContext &C(getGlobalContext());
25 Module M("test division", C);
26 IRBuilder<> Builder(C);
28 SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
29 Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
31 GlobalValue::ExternalLinkage, "F", &M);
32 assert(F->getArgumentList().size() == 2);
34 BasicBlock *BB = BasicBlock::Create(C, "", F);
35 Builder.SetInsertPoint(BB);
37 Function::arg_iterator AI = F->arg_begin();
41 Value *Div = Builder.CreateSDiv(A, B);
42 EXPECT_TRUE(BB->front().getOpcode() == Instruction::SDiv);
44 Value *Ret = Builder.CreateRet(Div);
46 expandDivision(cast<BinaryOperator>(Div));
47 EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr);
49 Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
50 EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::Sub);
53 TEST(IntegerDivision, UDiv) {
54 LLVMContext &C(getGlobalContext());
55 Module M("test division", C);
56 IRBuilder<> Builder(C);
58 SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
59 Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
61 GlobalValue::ExternalLinkage, "F", &M);
62 assert(F->getArgumentList().size() == 2);
64 BasicBlock *BB = BasicBlock::Create(C, "", F);
65 Builder.SetInsertPoint(BB);
67 Function::arg_iterator AI = F->arg_begin();
71 Value *Div = Builder.CreateUDiv(A, B);
72 EXPECT_TRUE(BB->front().getOpcode() == Instruction::UDiv);
74 Value *Ret = Builder.CreateRet(Div);
76 expandDivision(cast<BinaryOperator>(Div));
77 EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp);
79 Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
80 EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::PHI);
83 TEST(IntegerDivision, SRem) {
84 LLVMContext &C(getGlobalContext());
85 Module M("test remainder", C);
86 IRBuilder<> Builder(C);
88 SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
89 Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
91 GlobalValue::ExternalLinkage, "F", &M);
92 assert(F->getArgumentList().size() == 2);
94 BasicBlock *BB = BasicBlock::Create(C, "", F);
95 Builder.SetInsertPoint(BB);
97 Function::arg_iterator AI = F->arg_begin();
101 Value *Rem = Builder.CreateSRem(A, B);
102 EXPECT_TRUE(BB->front().getOpcode() == Instruction::SRem);
104 Value *Ret = Builder.CreateRet(Rem);
106 expandRemainder(cast<BinaryOperator>(Rem));
107 EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr);
109 Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
110 EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
113 TEST(IntegerDivision, URem) {
114 LLVMContext &C(getGlobalContext());
115 Module M("test remainder", C);
116 IRBuilder<> Builder(C);
118 SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
119 Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
121 GlobalValue::ExternalLinkage, "F", &M);
122 assert(F->getArgumentList().size() == 2);
124 BasicBlock *BB = BasicBlock::Create(C, "", F);
125 Builder.SetInsertPoint(BB);
127 Function::arg_iterator AI = F->arg_begin();
131 Value *Rem = Builder.CreateURem(A, B);
132 EXPECT_TRUE(BB->front().getOpcode() == Instruction::URem);
134 Value *Ret = Builder.CreateRet(Rem);
136 expandRemainder(cast<BinaryOperator>(Rem));
137 EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp);
139 Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
140 EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
144 TEST(IntegerDivision, SDiv64) {
145 LLVMContext &C(getGlobalContext());
146 Module M("test division", C);
147 IRBuilder<> Builder(C);
149 SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty());
150 Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
152 GlobalValue::ExternalLinkage, "F", &M);
153 assert(F->getArgumentList().size() == 2);
155 BasicBlock *BB = BasicBlock::Create(C, "", F);
156 Builder.SetInsertPoint(BB);
158 Function::arg_iterator AI = F->arg_begin();
162 Value *Div = Builder.CreateSDiv(A, B);
163 EXPECT_TRUE(BB->front().getOpcode() == Instruction::SDiv);
165 Value *Ret = Builder.CreateRet(Div);
167 expandDivision(cast<BinaryOperator>(Div));
168 EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr);
170 Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
171 EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::Sub);
174 TEST(IntegerDivision, UDiv64) {
175 LLVMContext &C(getGlobalContext());
176 Module M("test division", C);
177 IRBuilder<> Builder(C);
179 SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty());
180 Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
182 GlobalValue::ExternalLinkage, "F", &M);
183 assert(F->getArgumentList().size() == 2);
185 BasicBlock *BB = BasicBlock::Create(C, "", F);
186 Builder.SetInsertPoint(BB);
188 Function::arg_iterator AI = F->arg_begin();
192 Value *Div = Builder.CreateUDiv(A, B);
193 EXPECT_TRUE(BB->front().getOpcode() == Instruction::UDiv);
195 Value *Ret = Builder.CreateRet(Div);
197 expandDivision(cast<BinaryOperator>(Div));
198 EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp);
200 Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
201 EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::PHI);
204 TEST(IntegerDivision, SRem64) {
205 LLVMContext &C(getGlobalContext());
206 Module M("test remainder", C);
207 IRBuilder<> Builder(C);
209 SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty());
210 Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
212 GlobalValue::ExternalLinkage, "F", &M);
213 assert(F->getArgumentList().size() == 2);
215 BasicBlock *BB = BasicBlock::Create(C, "", F);
216 Builder.SetInsertPoint(BB);
218 Function::arg_iterator AI = F->arg_begin();
222 Value *Rem = Builder.CreateSRem(A, B);
223 EXPECT_TRUE(BB->front().getOpcode() == Instruction::SRem);
225 Value *Ret = Builder.CreateRet(Rem);
227 expandRemainder(cast<BinaryOperator>(Rem));
228 EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr);
230 Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
231 EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
234 TEST(IntegerDivision, URem64) {
235 LLVMContext &C(getGlobalContext());
236 Module M("test remainder", C);
237 IRBuilder<> Builder(C);
239 SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty());
240 Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
242 GlobalValue::ExternalLinkage, "F", &M);
243 assert(F->getArgumentList().size() == 2);
245 BasicBlock *BB = BasicBlock::Create(C, "", F);
246 Builder.SetInsertPoint(BB);
248 Function::arg_iterator AI = F->arg_begin();
252 Value *Rem = Builder.CreateURem(A, B);
253 EXPECT_TRUE(BB->front().getOpcode() == Instruction::URem);
255 Value *Ret = Builder.CreateRet(Rem);
257 expandRemainder(cast<BinaryOperator>(Rem));
258 EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp);
260 Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
261 EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);