1 //===- IntegerDivision.cpp - Unit tests for the integer division code -----===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Transforms/Utils/IntegerDivision.h"
10 #include "llvm/IR/BasicBlock.h"
11 #include "llvm/IR/Function.h"
12 #include "llvm/IR/GlobalValue.h"
13 #include "llvm/IR/IRBuilder.h"
14 #include "llvm/IR/Module.h"
15 #include "gtest/gtest.h"
22 TEST(IntegerDivision
, SDiv
) {
24 Module
M("test division", C
);
25 IRBuilder
<> Builder(C
);
27 SmallVector
<Type
*, 2> ArgTys(2, Builder
.getInt32Ty());
28 Function
*F
= Function::Create(FunctionType::get(Builder
.getInt32Ty(),
30 GlobalValue::ExternalLinkage
, "F", &M
);
31 assert(F
->arg_size() == 2);
33 BasicBlock
*BB
= BasicBlock::Create(C
, "", F
);
34 Builder
.SetInsertPoint(BB
);
36 Function::arg_iterator AI
= F
->arg_begin();
40 Value
*Div
= Builder
.CreateSDiv(A
, B
);
41 EXPECT_TRUE(BB
->front().getOpcode() == Instruction::SDiv
);
43 Value
*Ret
= Builder
.CreateRet(Div
);
45 expandDivision(cast
<BinaryOperator
>(Div
));
46 EXPECT_TRUE(BB
->front().getOpcode() == Instruction::AShr
);
48 Instruction
* Quotient
= dyn_cast
<Instruction
>(cast
<User
>(Ret
)->getOperand(0));
49 EXPECT_TRUE(Quotient
&& Quotient
->getOpcode() == Instruction::Sub
);
52 TEST(IntegerDivision
, UDiv
) {
54 Module
M("test division", C
);
55 IRBuilder
<> Builder(C
);
57 SmallVector
<Type
*, 2> ArgTys(2, Builder
.getInt32Ty());
58 Function
*F
= Function::Create(FunctionType::get(Builder
.getInt32Ty(),
60 GlobalValue::ExternalLinkage
, "F", &M
);
61 assert(F
->arg_size() == 2);
63 BasicBlock
*BB
= BasicBlock::Create(C
, "", F
);
64 Builder
.SetInsertPoint(BB
);
66 Function::arg_iterator AI
= F
->arg_begin();
70 Value
*Div
= Builder
.CreateUDiv(A
, B
);
71 EXPECT_TRUE(BB
->front().getOpcode() == Instruction::UDiv
);
73 Value
*Ret
= Builder
.CreateRet(Div
);
75 expandDivision(cast
<BinaryOperator
>(Div
));
76 EXPECT_TRUE(BB
->front().getOpcode() == Instruction::ICmp
);
78 Instruction
* Quotient
= dyn_cast
<Instruction
>(cast
<User
>(Ret
)->getOperand(0));
79 EXPECT_TRUE(Quotient
&& Quotient
->getOpcode() == Instruction::PHI
);
82 TEST(IntegerDivision
, SRem
) {
84 Module
M("test remainder", C
);
85 IRBuilder
<> Builder(C
);
87 SmallVector
<Type
*, 2> ArgTys(2, Builder
.getInt32Ty());
88 Function
*F
= Function::Create(FunctionType::get(Builder
.getInt32Ty(),
90 GlobalValue::ExternalLinkage
, "F", &M
);
91 assert(F
->arg_size() == 2);
93 BasicBlock
*BB
= BasicBlock::Create(C
, "", F
);
94 Builder
.SetInsertPoint(BB
);
96 Function::arg_iterator AI
= F
->arg_begin();
100 Value
*Rem
= Builder
.CreateSRem(A
, B
);
101 EXPECT_TRUE(BB
->front().getOpcode() == Instruction::SRem
);
103 Value
*Ret
= Builder
.CreateRet(Rem
);
105 expandRemainder(cast
<BinaryOperator
>(Rem
));
106 EXPECT_TRUE(BB
->front().getOpcode() == Instruction::AShr
);
108 Instruction
* Remainder
= dyn_cast
<Instruction
>(cast
<User
>(Ret
)->getOperand(0));
109 EXPECT_TRUE(Remainder
&& Remainder
->getOpcode() == Instruction::Sub
);
112 TEST(IntegerDivision
, URem
) {
114 Module
M("test remainder", C
);
115 IRBuilder
<> Builder(C
);
117 SmallVector
<Type
*, 2> ArgTys(2, Builder
.getInt32Ty());
118 Function
*F
= Function::Create(FunctionType::get(Builder
.getInt32Ty(),
120 GlobalValue::ExternalLinkage
, "F", &M
);
121 assert(F
->arg_size() == 2);
123 BasicBlock
*BB
= BasicBlock::Create(C
, "", F
);
124 Builder
.SetInsertPoint(BB
);
126 Function::arg_iterator AI
= F
->arg_begin();
130 Value
*Rem
= Builder
.CreateURem(A
, B
);
131 EXPECT_TRUE(BB
->front().getOpcode() == Instruction::URem
);
133 Value
*Ret
= Builder
.CreateRet(Rem
);
135 expandRemainder(cast
<BinaryOperator
>(Rem
));
136 EXPECT_TRUE(BB
->front().getOpcode() == Instruction::ICmp
);
138 Instruction
* Remainder
= dyn_cast
<Instruction
>(cast
<User
>(Ret
)->getOperand(0));
139 EXPECT_TRUE(Remainder
&& Remainder
->getOpcode() == Instruction::Sub
);
143 TEST(IntegerDivision
, SDiv64
) {
145 Module
M("test division", C
);
146 IRBuilder
<> Builder(C
);
148 SmallVector
<Type
*, 2> ArgTys(2, Builder
.getInt64Ty());
149 Function
*F
= Function::Create(FunctionType::get(Builder
.getInt64Ty(),
151 GlobalValue::ExternalLinkage
, "F", &M
);
152 assert(F
->arg_size() == 2);
154 BasicBlock
*BB
= BasicBlock::Create(C
, "", F
);
155 Builder
.SetInsertPoint(BB
);
157 Function::arg_iterator AI
= F
->arg_begin();
161 Value
*Div
= Builder
.CreateSDiv(A
, B
);
162 EXPECT_TRUE(BB
->front().getOpcode() == Instruction::SDiv
);
164 Value
*Ret
= Builder
.CreateRet(Div
);
166 expandDivision(cast
<BinaryOperator
>(Div
));
167 EXPECT_TRUE(BB
->front().getOpcode() == Instruction::AShr
);
169 Instruction
* Quotient
= dyn_cast
<Instruction
>(cast
<User
>(Ret
)->getOperand(0));
170 EXPECT_TRUE(Quotient
&& Quotient
->getOpcode() == Instruction::Sub
);
173 TEST(IntegerDivision
, UDiv64
) {
175 Module
M("test division", C
);
176 IRBuilder
<> Builder(C
);
178 SmallVector
<Type
*, 2> ArgTys(2, Builder
.getInt64Ty());
179 Function
*F
= Function::Create(FunctionType::get(Builder
.getInt64Ty(),
181 GlobalValue::ExternalLinkage
, "F", &M
);
182 assert(F
->arg_size() == 2);
184 BasicBlock
*BB
= BasicBlock::Create(C
, "", F
);
185 Builder
.SetInsertPoint(BB
);
187 Function::arg_iterator AI
= F
->arg_begin();
191 Value
*Div
= Builder
.CreateUDiv(A
, B
);
192 EXPECT_TRUE(BB
->front().getOpcode() == Instruction::UDiv
);
194 Value
*Ret
= Builder
.CreateRet(Div
);
196 expandDivision(cast
<BinaryOperator
>(Div
));
197 EXPECT_TRUE(BB
->front().getOpcode() == Instruction::ICmp
);
199 Instruction
* Quotient
= dyn_cast
<Instruction
>(cast
<User
>(Ret
)->getOperand(0));
200 EXPECT_TRUE(Quotient
&& Quotient
->getOpcode() == Instruction::PHI
);
203 TEST(IntegerDivision
, SRem64
) {
205 Module
M("test remainder", C
);
206 IRBuilder
<> Builder(C
);
208 SmallVector
<Type
*, 2> ArgTys(2, Builder
.getInt64Ty());
209 Function
*F
= Function::Create(FunctionType::get(Builder
.getInt64Ty(),
211 GlobalValue::ExternalLinkage
, "F", &M
);
212 assert(F
->arg_size() == 2);
214 BasicBlock
*BB
= BasicBlock::Create(C
, "", F
);
215 Builder
.SetInsertPoint(BB
);
217 Function::arg_iterator AI
= F
->arg_begin();
221 Value
*Rem
= Builder
.CreateSRem(A
, B
);
222 EXPECT_TRUE(BB
->front().getOpcode() == Instruction::SRem
);
224 Value
*Ret
= Builder
.CreateRet(Rem
);
226 expandRemainder(cast
<BinaryOperator
>(Rem
));
227 EXPECT_TRUE(BB
->front().getOpcode() == Instruction::AShr
);
229 Instruction
* Remainder
= dyn_cast
<Instruction
>(cast
<User
>(Ret
)->getOperand(0));
230 EXPECT_TRUE(Remainder
&& Remainder
->getOpcode() == Instruction::Sub
);
233 TEST(IntegerDivision
, URem64
) {
235 Module
M("test remainder", C
);
236 IRBuilder
<> Builder(C
);
238 SmallVector
<Type
*, 2> ArgTys(2, Builder
.getInt64Ty());
239 Function
*F
= Function::Create(FunctionType::get(Builder
.getInt64Ty(),
241 GlobalValue::ExternalLinkage
, "F", &M
);
242 assert(F
->arg_size() == 2);
244 BasicBlock
*BB
= BasicBlock::Create(C
, "", F
);
245 Builder
.SetInsertPoint(BB
);
247 Function::arg_iterator AI
= F
->arg_begin();
251 Value
*Rem
= Builder
.CreateURem(A
, B
);
252 EXPECT_TRUE(BB
->front().getOpcode() == Instruction::URem
);
254 Value
*Ret
= Builder
.CreateRet(Rem
);
256 expandRemainder(cast
<BinaryOperator
>(Rem
));
257 EXPECT_TRUE(BB
->front().getOpcode() == Instruction::ICmp
);
259 Instruction
* Remainder
= dyn_cast
<Instruction
>(cast
<User
>(Ret
)->getOperand(0));
260 EXPECT_TRUE(Remainder
&& Remainder
->getOpcode() == Instruction::Sub
);