IntegerDivisionTest.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. //===- IntegerDivision.cpp - Unit tests for the integer division code -----===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "llvm/Transforms/Utils/IntegerDivision.h"
  9. #include "llvm/IR/BasicBlock.h"
  10. #include "llvm/IR/Function.h"
  11. #include "llvm/IR/GlobalValue.h"
  12. #include "llvm/IR/IRBuilder.h"
  13. #include "llvm/IR/Module.h"
  14. #include "gtest/gtest.h"
  15. using namespace llvm;
  16. namespace {
  17. TEST(IntegerDivision, SDiv) {
  18. LLVMContext C;
  19. Module M("test division", C);
  20. IRBuilder<> Builder(C);
  21. SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
  22. Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
  23. ArgTys, false),
  24. GlobalValue::ExternalLinkage, "F", &M);
  25. assert(F->arg_size() == 2);
  26. BasicBlock *BB = BasicBlock::Create(C, "", F);
  27. Builder.SetInsertPoint(BB);
  28. Function::arg_iterator AI = F->arg_begin();
  29. Value *A = &*AI++;
  30. Value *B = &*AI++;
  31. Value *Div = Builder.CreateSDiv(A, B);
  32. EXPECT_TRUE(BB->front().getOpcode() == Instruction::SDiv);
  33. Value *Ret = Builder.CreateRet(Div);
  34. expandDivision(cast<BinaryOperator>(Div));
  35. EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr);
  36. Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
  37. EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::Sub);
  38. }
  39. TEST(IntegerDivision, UDiv) {
  40. LLVMContext C;
  41. Module M("test division", C);
  42. IRBuilder<> Builder(C);
  43. SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
  44. Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
  45. ArgTys, false),
  46. GlobalValue::ExternalLinkage, "F", &M);
  47. assert(F->arg_size() == 2);
  48. BasicBlock *BB = BasicBlock::Create(C, "", F);
  49. Builder.SetInsertPoint(BB);
  50. Function::arg_iterator AI = F->arg_begin();
  51. Value *A = &*AI++;
  52. Value *B = &*AI++;
  53. Value *Div = Builder.CreateUDiv(A, B);
  54. EXPECT_TRUE(BB->front().getOpcode() == Instruction::UDiv);
  55. Value *Ret = Builder.CreateRet(Div);
  56. expandDivision(cast<BinaryOperator>(Div));
  57. EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp);
  58. Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
  59. EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::PHI);
  60. }
  61. TEST(IntegerDivision, SRem) {
  62. LLVMContext C;
  63. Module M("test remainder", C);
  64. IRBuilder<> Builder(C);
  65. SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
  66. Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
  67. ArgTys, false),
  68. GlobalValue::ExternalLinkage, "F", &M);
  69. assert(F->arg_size() == 2);
  70. BasicBlock *BB = BasicBlock::Create(C, "", F);
  71. Builder.SetInsertPoint(BB);
  72. Function::arg_iterator AI = F->arg_begin();
  73. Value *A = &*AI++;
  74. Value *B = &*AI++;
  75. Value *Rem = Builder.CreateSRem(A, B);
  76. EXPECT_TRUE(BB->front().getOpcode() == Instruction::SRem);
  77. Value *Ret = Builder.CreateRet(Rem);
  78. expandRemainder(cast<BinaryOperator>(Rem));
  79. EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr);
  80. Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
  81. EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
  82. }
  83. TEST(IntegerDivision, URem) {
  84. LLVMContext C;
  85. Module M("test remainder", C);
  86. IRBuilder<> Builder(C);
  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->arg_size() == 2);
  92. BasicBlock *BB = BasicBlock::Create(C, "", F);
  93. Builder.SetInsertPoint(BB);
  94. Function::arg_iterator AI = F->arg_begin();
  95. Value *A = &*AI++;
  96. Value *B = &*AI++;
  97. Value *Rem = Builder.CreateURem(A, B);
  98. EXPECT_TRUE(BB->front().getOpcode() == Instruction::URem);
  99. Value *Ret = Builder.CreateRet(Rem);
  100. expandRemainder(cast<BinaryOperator>(Rem));
  101. EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp);
  102. Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
  103. EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
  104. }
  105. TEST(IntegerDivision, SDiv64) {
  106. LLVMContext C;
  107. Module M("test division", C);
  108. IRBuilder<> Builder(C);
  109. SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty());
  110. Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
  111. ArgTys, false),
  112. GlobalValue::ExternalLinkage, "F", &M);
  113. assert(F->arg_size() == 2);
  114. BasicBlock *BB = BasicBlock::Create(C, "", F);
  115. Builder.SetInsertPoint(BB);
  116. Function::arg_iterator AI = F->arg_begin();
  117. Value *A = &*AI++;
  118. Value *B = &*AI++;
  119. Value *Div = Builder.CreateSDiv(A, B);
  120. EXPECT_TRUE(BB->front().getOpcode() == Instruction::SDiv);
  121. Value *Ret = Builder.CreateRet(Div);
  122. expandDivision(cast<BinaryOperator>(Div));
  123. EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr);
  124. Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
  125. EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::Sub);
  126. }
  127. TEST(IntegerDivision, UDiv64) {
  128. LLVMContext C;
  129. Module M("test division", C);
  130. IRBuilder<> Builder(C);
  131. SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty());
  132. Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
  133. ArgTys, false),
  134. GlobalValue::ExternalLinkage, "F", &M);
  135. assert(F->arg_size() == 2);
  136. BasicBlock *BB = BasicBlock::Create(C, "", F);
  137. Builder.SetInsertPoint(BB);
  138. Function::arg_iterator AI = F->arg_begin();
  139. Value *A = &*AI++;
  140. Value *B = &*AI++;
  141. Value *Div = Builder.CreateUDiv(A, B);
  142. EXPECT_TRUE(BB->front().getOpcode() == Instruction::UDiv);
  143. Value *Ret = Builder.CreateRet(Div);
  144. expandDivision(cast<BinaryOperator>(Div));
  145. EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp);
  146. Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
  147. EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::PHI);
  148. }
  149. TEST(IntegerDivision, SRem64) {
  150. LLVMContext C;
  151. Module M("test remainder", C);
  152. IRBuilder<> Builder(C);
  153. SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty());
  154. Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
  155. ArgTys, false),
  156. GlobalValue::ExternalLinkage, "F", &M);
  157. assert(F->arg_size() == 2);
  158. BasicBlock *BB = BasicBlock::Create(C, "", F);
  159. Builder.SetInsertPoint(BB);
  160. Function::arg_iterator AI = F->arg_begin();
  161. Value *A = &*AI++;
  162. Value *B = &*AI++;
  163. Value *Rem = Builder.CreateSRem(A, B);
  164. EXPECT_TRUE(BB->front().getOpcode() == Instruction::SRem);
  165. Value *Ret = Builder.CreateRet(Rem);
  166. expandRemainder(cast<BinaryOperator>(Rem));
  167. EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr);
  168. Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
  169. EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
  170. }
  171. TEST(IntegerDivision, URem64) {
  172. LLVMContext C;
  173. Module M("test remainder", C);
  174. IRBuilder<> Builder(C);
  175. SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty());
  176. Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
  177. ArgTys, false),
  178. GlobalValue::ExternalLinkage, "F", &M);
  179. assert(F->arg_size() == 2);
  180. BasicBlock *BB = BasicBlock::Create(C, "", F);
  181. Builder.SetInsertPoint(BB);
  182. Function::arg_iterator AI = F->arg_begin();
  183. Value *A = &*AI++;
  184. Value *B = &*AI++;
  185. Value *Rem = Builder.CreateURem(A, B);
  186. EXPECT_TRUE(BB->front().getOpcode() == Instruction::URem);
  187. Value *Ret = Builder.CreateRet(Rem);
  188. expandRemainder(cast<BinaryOperator>(Rem));
  189. EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp);
  190. Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
  191. EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
  192. }
  193. }