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