18267b333SNico Weber //===- IntegerDivision.cpp - Unit tests for the integer division code -----===//
28267b333SNico Weber //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68267b333SNico Weber //
78267b333SNico Weber //===----------------------------------------------------------------------===//
88267b333SNico Weber
98267b333SNico Weber #include "llvm/Transforms/Utils/IntegerDivision.h"
108267b333SNico Weber #include "llvm/IR/BasicBlock.h"
118267b333SNico Weber #include "llvm/IR/Function.h"
128267b333SNico Weber #include "llvm/IR/GlobalValue.h"
138267b333SNico Weber #include "llvm/IR/IRBuilder.h"
148267b333SNico Weber #include "llvm/IR/Module.h"
158267b333SNico Weber #include "gtest/gtest.h"
168267b333SNico Weber
178267b333SNico Weber using namespace llvm;
188267b333SNico Weber
198267b333SNico Weber namespace {
208267b333SNico Weber
218267b333SNico Weber
TEST(IntegerDivision,SDiv)228267b333SNico Weber TEST(IntegerDivision, SDiv) {
238267b333SNico Weber LLVMContext C;
248267b333SNico Weber Module M("test division", C);
258267b333SNico Weber IRBuilder<> Builder(C);
268267b333SNico Weber
278267b333SNico Weber SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
288267b333SNico Weber Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
298267b333SNico Weber ArgTys, false),
308267b333SNico Weber GlobalValue::ExternalLinkage, "F", &M);
318267b333SNico Weber assert(F->arg_size() == 2);
328267b333SNico Weber
338267b333SNico Weber BasicBlock *BB = BasicBlock::Create(C, "", F);
348267b333SNico Weber Builder.SetInsertPoint(BB);
358267b333SNico Weber
368267b333SNico Weber Function::arg_iterator AI = F->arg_begin();
378267b333SNico Weber Value *A = &*AI++;
388267b333SNico Weber Value *B = &*AI++;
398267b333SNico Weber
408267b333SNico Weber Value *Div = Builder.CreateSDiv(A, B);
418267b333SNico Weber EXPECT_TRUE(BB->front().getOpcode() == Instruction::SDiv);
428267b333SNico Weber
438267b333SNico Weber Value *Ret = Builder.CreateRet(Div);
448267b333SNico Weber
458267b333SNico Weber expandDivision(cast<BinaryOperator>(Div));
46*ace05124SCraig Topper EXPECT_TRUE(BB->front().getOpcode() == Instruction::Freeze);
478267b333SNico Weber
488267b333SNico Weber Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
498267b333SNico Weber EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::Sub);
508267b333SNico Weber }
518267b333SNico Weber
TEST(IntegerDivision,UDiv)528267b333SNico Weber TEST(IntegerDivision, UDiv) {
538267b333SNico Weber LLVMContext C;
548267b333SNico Weber Module M("test division", C);
558267b333SNico Weber IRBuilder<> Builder(C);
568267b333SNico Weber
578267b333SNico Weber SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
588267b333SNico Weber Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
598267b333SNico Weber ArgTys, false),
608267b333SNico Weber GlobalValue::ExternalLinkage, "F", &M);
618267b333SNico Weber assert(F->arg_size() == 2);
628267b333SNico Weber
638267b333SNico Weber BasicBlock *BB = BasicBlock::Create(C, "", F);
648267b333SNico Weber Builder.SetInsertPoint(BB);
658267b333SNico Weber
668267b333SNico Weber Function::arg_iterator AI = F->arg_begin();
678267b333SNico Weber Value *A = &*AI++;
688267b333SNico Weber Value *B = &*AI++;
698267b333SNico Weber
708267b333SNico Weber Value *Div = Builder.CreateUDiv(A, B);
718267b333SNico Weber EXPECT_TRUE(BB->front().getOpcode() == Instruction::UDiv);
728267b333SNico Weber
738267b333SNico Weber Value *Ret = Builder.CreateRet(Div);
748267b333SNico Weber
758267b333SNico Weber expandDivision(cast<BinaryOperator>(Div));
76*ace05124SCraig Topper EXPECT_TRUE(BB->front().getOpcode() == Instruction::Freeze);
778267b333SNico Weber
788267b333SNico Weber Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
798267b333SNico Weber EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::PHI);
808267b333SNico Weber }
818267b333SNico Weber
TEST(IntegerDivision,SRem)828267b333SNico Weber TEST(IntegerDivision, SRem) {
838267b333SNico Weber LLVMContext C;
848267b333SNico Weber Module M("test remainder", C);
858267b333SNico Weber IRBuilder<> Builder(C);
868267b333SNico Weber
878267b333SNico Weber SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
888267b333SNico Weber Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
898267b333SNico Weber ArgTys, false),
908267b333SNico Weber GlobalValue::ExternalLinkage, "F", &M);
918267b333SNico Weber assert(F->arg_size() == 2);
928267b333SNico Weber
938267b333SNico Weber BasicBlock *BB = BasicBlock::Create(C, "", F);
948267b333SNico Weber Builder.SetInsertPoint(BB);
958267b333SNico Weber
968267b333SNico Weber Function::arg_iterator AI = F->arg_begin();
978267b333SNico Weber Value *A = &*AI++;
988267b333SNico Weber Value *B = &*AI++;
998267b333SNico Weber
1008267b333SNico Weber Value *Rem = Builder.CreateSRem(A, B);
1018267b333SNico Weber EXPECT_TRUE(BB->front().getOpcode() == Instruction::SRem);
1028267b333SNico Weber
1038267b333SNico Weber Value *Ret = Builder.CreateRet(Rem);
1048267b333SNico Weber
1058267b333SNico Weber expandRemainder(cast<BinaryOperator>(Rem));
106*ace05124SCraig Topper EXPECT_TRUE(BB->front().getOpcode() == Instruction::Freeze);
1078267b333SNico Weber
1088267b333SNico Weber Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
1098267b333SNico Weber EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
1108267b333SNico Weber }
1118267b333SNico Weber
TEST(IntegerDivision,URem)1128267b333SNico Weber TEST(IntegerDivision, URem) {
1138267b333SNico Weber LLVMContext C;
1148267b333SNico Weber Module M("test remainder", C);
1158267b333SNico Weber IRBuilder<> Builder(C);
1168267b333SNico Weber
1178267b333SNico Weber SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
1188267b333SNico Weber Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
1198267b333SNico Weber ArgTys, false),
1208267b333SNico Weber GlobalValue::ExternalLinkage, "F", &M);
1218267b333SNico Weber assert(F->arg_size() == 2);
1228267b333SNico Weber
1238267b333SNico Weber BasicBlock *BB = BasicBlock::Create(C, "", F);
1248267b333SNico Weber Builder.SetInsertPoint(BB);
1258267b333SNico Weber
1268267b333SNico Weber Function::arg_iterator AI = F->arg_begin();
1278267b333SNico Weber Value *A = &*AI++;
1288267b333SNico Weber Value *B = &*AI++;
1298267b333SNico Weber
1308267b333SNico Weber Value *Rem = Builder.CreateURem(A, B);
1318267b333SNico Weber EXPECT_TRUE(BB->front().getOpcode() == Instruction::URem);
1328267b333SNico Weber
1338267b333SNico Weber Value *Ret = Builder.CreateRet(Rem);
1348267b333SNico Weber
1358267b333SNico Weber expandRemainder(cast<BinaryOperator>(Rem));
136*ace05124SCraig Topper EXPECT_TRUE(BB->front().getOpcode() == Instruction::Freeze);
1378267b333SNico Weber
1388267b333SNico Weber Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
1398267b333SNico Weber EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
1408267b333SNico Weber }
1418267b333SNico Weber
1428267b333SNico Weber
TEST(IntegerDivision,SDiv64)1438267b333SNico Weber TEST(IntegerDivision, SDiv64) {
1448267b333SNico Weber LLVMContext C;
1458267b333SNico Weber Module M("test division", C);
1468267b333SNico Weber IRBuilder<> Builder(C);
1478267b333SNico Weber
1488267b333SNico Weber SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty());
1498267b333SNico Weber Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
1508267b333SNico Weber ArgTys, false),
1518267b333SNico Weber GlobalValue::ExternalLinkage, "F", &M);
1528267b333SNico Weber assert(F->arg_size() == 2);
1538267b333SNico Weber
1548267b333SNico Weber BasicBlock *BB = BasicBlock::Create(C, "", F);
1558267b333SNico Weber Builder.SetInsertPoint(BB);
1568267b333SNico Weber
1578267b333SNico Weber Function::arg_iterator AI = F->arg_begin();
1588267b333SNico Weber Value *A = &*AI++;
1598267b333SNico Weber Value *B = &*AI++;
1608267b333SNico Weber
1618267b333SNico Weber Value *Div = Builder.CreateSDiv(A, B);
1628267b333SNico Weber EXPECT_TRUE(BB->front().getOpcode() == Instruction::SDiv);
1638267b333SNico Weber
1648267b333SNico Weber Value *Ret = Builder.CreateRet(Div);
1658267b333SNico Weber
1668267b333SNico Weber expandDivision(cast<BinaryOperator>(Div));
167*ace05124SCraig Topper EXPECT_TRUE(BB->front().getOpcode() == Instruction::Freeze);
1688267b333SNico Weber
1698267b333SNico Weber Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
1708267b333SNico Weber EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::Sub);
1718267b333SNico Weber }
1728267b333SNico Weber
TEST(IntegerDivision,UDiv64)1738267b333SNico Weber TEST(IntegerDivision, UDiv64) {
1748267b333SNico Weber LLVMContext C;
1758267b333SNico Weber Module M("test division", C);
1768267b333SNico Weber IRBuilder<> Builder(C);
1778267b333SNico Weber
1788267b333SNico Weber SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty());
1798267b333SNico Weber Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
1808267b333SNico Weber ArgTys, false),
1818267b333SNico Weber GlobalValue::ExternalLinkage, "F", &M);
1828267b333SNico Weber assert(F->arg_size() == 2);
1838267b333SNico Weber
1848267b333SNico Weber BasicBlock *BB = BasicBlock::Create(C, "", F);
1858267b333SNico Weber Builder.SetInsertPoint(BB);
1868267b333SNico Weber
1878267b333SNico Weber Function::arg_iterator AI = F->arg_begin();
1888267b333SNico Weber Value *A = &*AI++;
1898267b333SNico Weber Value *B = &*AI++;
1908267b333SNico Weber
1918267b333SNico Weber Value *Div = Builder.CreateUDiv(A, B);
1928267b333SNico Weber EXPECT_TRUE(BB->front().getOpcode() == Instruction::UDiv);
1938267b333SNico Weber
1948267b333SNico Weber Value *Ret = Builder.CreateRet(Div);
1958267b333SNico Weber
1968267b333SNico Weber expandDivision(cast<BinaryOperator>(Div));
197*ace05124SCraig Topper EXPECT_TRUE(BB->front().getOpcode() == Instruction::Freeze);
1988267b333SNico Weber
1998267b333SNico Weber Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
2008267b333SNico Weber EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::PHI);
2018267b333SNico Weber }
2028267b333SNico Weber
TEST(IntegerDivision,SRem64)2038267b333SNico Weber TEST(IntegerDivision, SRem64) {
2048267b333SNico Weber LLVMContext C;
2058267b333SNico Weber Module M("test remainder", C);
2068267b333SNico Weber IRBuilder<> Builder(C);
2078267b333SNico Weber
2088267b333SNico Weber SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty());
2098267b333SNico Weber Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
2108267b333SNico Weber ArgTys, false),
2118267b333SNico Weber GlobalValue::ExternalLinkage, "F", &M);
2128267b333SNico Weber assert(F->arg_size() == 2);
2138267b333SNico Weber
2148267b333SNico Weber BasicBlock *BB = BasicBlock::Create(C, "", F);
2158267b333SNico Weber Builder.SetInsertPoint(BB);
2168267b333SNico Weber
2178267b333SNico Weber Function::arg_iterator AI = F->arg_begin();
2188267b333SNico Weber Value *A = &*AI++;
2198267b333SNico Weber Value *B = &*AI++;
2208267b333SNico Weber
2218267b333SNico Weber Value *Rem = Builder.CreateSRem(A, B);
2228267b333SNico Weber EXPECT_TRUE(BB->front().getOpcode() == Instruction::SRem);
2238267b333SNico Weber
2248267b333SNico Weber Value *Ret = Builder.CreateRet(Rem);
2258267b333SNico Weber
2268267b333SNico Weber expandRemainder(cast<BinaryOperator>(Rem));
227*ace05124SCraig Topper EXPECT_TRUE(BB->front().getOpcode() == Instruction::Freeze);
2288267b333SNico Weber
2298267b333SNico Weber Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
2308267b333SNico Weber EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
2318267b333SNico Weber }
2328267b333SNico Weber
TEST(IntegerDivision,URem64)2338267b333SNico Weber TEST(IntegerDivision, URem64) {
2348267b333SNico Weber LLVMContext C;
2358267b333SNico Weber Module M("test remainder", C);
2368267b333SNico Weber IRBuilder<> Builder(C);
2378267b333SNico Weber
2388267b333SNico Weber SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty());
2398267b333SNico Weber Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
2408267b333SNico Weber ArgTys, false),
2418267b333SNico Weber GlobalValue::ExternalLinkage, "F", &M);
2428267b333SNico Weber assert(F->arg_size() == 2);
2438267b333SNico Weber
2448267b333SNico Weber BasicBlock *BB = BasicBlock::Create(C, "", F);
2458267b333SNico Weber Builder.SetInsertPoint(BB);
2468267b333SNico Weber
2478267b333SNico Weber Function::arg_iterator AI = F->arg_begin();
2488267b333SNico Weber Value *A = &*AI++;
2498267b333SNico Weber Value *B = &*AI++;
2508267b333SNico Weber
2518267b333SNico Weber Value *Rem = Builder.CreateURem(A, B);
2528267b333SNico Weber EXPECT_TRUE(BB->front().getOpcode() == Instruction::URem);
2538267b333SNico Weber
2548267b333SNico Weber Value *Ret = Builder.CreateRet(Rem);
2558267b333SNico Weber
2568267b333SNico Weber expandRemainder(cast<BinaryOperator>(Rem));
257*ace05124SCraig Topper EXPECT_TRUE(BB->front().getOpcode() == Instruction::Freeze);
2588267b333SNico Weber
2598267b333SNico Weber Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
2608267b333SNico Weber EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
2618267b333SNico Weber }
2628267b333SNico Weber
2638267b333SNico Weber }
264