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