[InstCombine] Signed saturation tests. NFC
[llvm-complete.git] / unittests / Transforms / Utils / IntegerDivisionTest.cpp
blob79946735f8546855534231d94b1dec571ccd3702
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 //===----------------------------------------------------------------------===//
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"
17 using namespace llvm;
19 namespace {
22 TEST(IntegerDivision, SDiv) {
23 LLVMContext C;
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(),
29 ArgTys, false),
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();
37 Value *A = &*AI++;
38 Value *B = &*AI++;
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) {
53 LLVMContext C;
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(),
59 ArgTys, false),
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();
67 Value *A = &*AI++;
68 Value *B = &*AI++;
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) {
83 LLVMContext C;
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(),
89 ArgTys, false),
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();
97 Value *A = &*AI++;
98 Value *B = &*AI++;
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) {
113 LLVMContext C;
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(),
119 ArgTys, false),
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();
127 Value *A = &*AI++;
128 Value *B = &*AI++;
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) {
144 LLVMContext C;
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(),
150 ArgTys, false),
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();
158 Value *A = &*AI++;
159 Value *B = &*AI++;
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) {
174 LLVMContext C;
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(),
180 ArgTys, false),
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();
188 Value *A = &*AI++;
189 Value *B = &*AI++;
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) {
204 LLVMContext C;
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(),
210 ArgTys, false),
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();
218 Value *A = &*AI++;
219 Value *B = &*AI++;
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) {
234 LLVMContext C;
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(),
240 ArgTys, false),
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();
248 Value *A = &*AI++;
249 Value *B = &*AI++;
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);