Home | History | Annotate | Download | only in Utils
      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;
     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;
     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;
     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;
    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;
    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;
    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;
    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;
    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