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 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