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 TEST(IntegerDivision, SDiv) { 23 LLVMContext &C(getGlobalContext()); 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->getArgumentList().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 52 TEST(IntegerDivision, UDiv) { 53 LLVMContext &C(getGlobalContext()); 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->getArgumentList().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 82 TEST(IntegerDivision, SRem) { 83 LLVMContext &C(getGlobalContext()); 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->getArgumentList().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 112 TEST(IntegerDivision, URem) { 113 LLVMContext &C(getGlobalContext()); 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->getArgumentList().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 } 143