llvm.org GIT mirror llvm / 1b3ab91
Add support for software expansion of 64-bit integer division instructions. Patch by Dmitri Shtilman! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@195116 91177308-0d34-0410-b5e6-96231b3b80d8 Michael Ilseman 5 years ago
3 changed file(s) with 349 addition(s) and 62 deletion(s). Raw diff Collapse all Expand all
66 //
77 //===----------------------------------------------------------------------===//
88 //
9 // This file contains an implementation of 32bit integer division for targets
10 // that don't have native support. It's largely derived from compiler-rt's
11 // implementation of __udivsi3, but hand-tuned for targets that prefer less
12 // control flow.
9 // This file contains an implementation of 32bit and 64bit scalar integer
10 // division for targets that don't have native support. It's largely derived
11 // from compiler-rt's implementations of __udivsi3 and __udivmoddi4,
12 // but hand-tuned for targets that prefer less control flow.
1313 //
1414 //===----------------------------------------------------------------------===//
1515
2525 /// Generate code to calculate the remainder of two integers, replacing Rem
2626 /// with the generated code. This currently generates code using the udiv
2727 /// expansion, but future work includes generating more specialized code,
28 /// e.g. when more information about the operands are known. Currently only
29 /// implements 32bit scalar division (due to udiv's limitation), but future
30 /// work is removing this limitation.
28 /// e.g. when more information about the operands are known. Implements both
29 /// 32bit and 64bit scalar division.
3130 ///
3231 /// @brief Replace Rem with generated code.
3332 bool expandRemainder(BinaryOperator *Rem);
3534 /// Generate code to divide two integers, replacing Div with the generated
3635 /// code. This currently generates code similarly to compiler-rt's
3736 /// implementations, but future work includes generating more specialized code
38 /// when more information about the operands are known. Currently only
39 /// implements 32bit scalar division, but future work is removing this
40 /// limitation.
37 /// when more information about the operands are known. Implements both
38 /// 32bit and 64bit scalar division.
4139 ///
4240 /// @brief Replace Div with generated code.
4341 bool expandDivision(BinaryOperator* Div);
4442
4543 /// Generate code to calculate the remainder of two integers, replacing Rem
46 /// with the generated code. Uses the above 32bit routine, therefore adequate
47 /// for targets with little or no support for less than 32 bit arithmetic.
44 /// with the generated code. Uses ExpandReminder with a 32bit Rem which
45 /// makes it useful for targets with little or no support for less than
46 /// 32 bit arithmetic.
4847 ///
4948 /// @brief Replace Rem with generated code.
5049 bool expandRemainderUpTo32Bits(BinaryOperator *Rem);
5150
51 /// Generate code to calculate the remainder of two integers, replacing Rem
52 /// with the generated code. Uses ExpandReminder with a 64bit Rem.
53 ///
54 /// @brief Replace Rem with generated code.
55 bool expandRemainderUpTo64Bits(BinaryOperator *Rem);
56
5257 /// Generate code to divide two integers, replacing Div with the generated
53 /// code. Uses the above 32bit routine, therefore adequate for targets with
54 /// little or no support for less than 32 bit arithmetic.
58 /// code. Uses ExpandDivision with a 32bit Div which makes it useful for
59 /// targets with little or no support for less than 32 bit arithmetic.
5560 ///
5661 /// @brief Replace Rem with generated code.
5762 bool expandDivisionUpTo32Bits(BinaryOperator *Div);
5863
64 /// Generate code to divide two integers, replacing Div with the generated
65 /// code. Uses ExpandDivision with a 64bit Div.
66 ///
67 /// @brief Replace Rem with generated code.
68 bool expandDivisionUpTo64Bits(BinaryOperator *Div);
69
5970 } // End llvm namespace
6071
6172 #endif
66 //
77 //===----------------------------------------------------------------------===//
88 //
9 // This file contains an implementation of 32bit scalar integer division for
10 // targets that don't have native support. It's largely derived from
11 // compiler-rt's implementation of __udivsi3, but hand-tuned to reduce the
12 // amount of control flow
9 // This file contains an implementation of 32bit and 64bit scalar integer
10 // division for targets that don't have native support. It's largely derived
11 // from compiler-rt's implementations of __udivsi3 and __udivmoddi4,
12 // but hand-tuned for targets that prefer less control flow.
1313 //
1414 //===----------------------------------------------------------------------===//
1515
1919 #include "llvm/IR/IRBuilder.h"
2020 #include "llvm/IR/Instructions.h"
2121 #include "llvm/IR/Intrinsics.h"
22 #include
2223
2324 using namespace llvm;
2425
3031 /// be expanded if the user wishes
3132 static Value *generateSignedRemainderCode(Value *Dividend, Value *Divisor,
3233 IRBuilder<> &Builder) {
33 ConstantInt *ThirtyOne = Builder.getInt32(31);
34 unsigned BitWidth = Dividend->getType()->getIntegerBitWidth();
35 ConstantInt *Shift;
36
37 if (BitWidth == 64) {
38 Shift = Builder.getInt64(63);
39 } else {
40 assert(BitWidth == 32 && "Unexpected bit width");
41 Shift = Builder.getInt32(31);
42 }
43
44 // Following instructions are generated for both i32 (shift 31) and
45 // i64 (shift 63).
3446
3547 // ; %dividend_sgn = ashr i32 %dividend, 31
3648 // ; %divisor_sgn = ashr i32 %divisor, 31
4153 // ; %urem = urem i32 %dividend, %divisor
4254 // ; %xored = xor i32 %urem, %dividend_sgn
4355 // ; %srem = sub i32 %xored, %dividend_sgn
44 Value *DividendSign = Builder.CreateAShr(Dividend, ThirtyOne);
45 Value *DivisorSign = Builder.CreateAShr(Divisor, ThirtyOne);
56 Value *DividendSign = Builder.CreateAShr(Dividend, Shift);
57 Value *DivisorSign = Builder.CreateAShr(Divisor, Shift);
4658 Value *DvdXor = Builder.CreateXor(Dividend, DividendSign);
4759 Value *DvsXor = Builder.CreateXor(Divisor, DivisorSign);
4860 Value *UDividend = Builder.CreateSub(DvdXor, DividendSign);
6779 IRBuilder<> &Builder) {
6880 // Remainder = Dividend - Quotient*Divisor
6981
82 // Following instructions are generated for both i32 and i64
83
7084 // ; %quotient = udiv i32 %dividend, %divisor
7185 // ; %product = mul i32 %divisor, %quotient
7286 // ; %remainder = sub i32 %dividend, %product
87101 /// present, i.e. not folded), ready to be expanded if the user wishes.
88102 static Value *generateSignedDivisionCode(Value *Dividend, Value *Divisor,
89103 IRBuilder<> &Builder) {
90 // Implementation taken from compiler-rt's __divsi3
91
92 ConstantInt *ThirtyOne = Builder.getInt32(31);
104 // Implementation taken from compiler-rt's __divsi3 and __divdi3
105
106 unsigned BitWidth = Dividend->getType()->getIntegerBitWidth();
107 ConstantInt *Shift;
108
109 if (BitWidth == 64) {
110 Shift = Builder.getInt64(63);
111 } else {
112 assert(BitWidth == 32 && "Unexpected bit width");
113 Shift = Builder.getInt32(31);
114 }
115
116 // Following instructions are generated for both i32 (shift 31) and
117 // i64 (shift 63).
93118
94119 // ; %tmp = ashr i32 %dividend, 31
95120 // ; %tmp1 = ashr i32 %divisor, 31
101126 // ; %q_mag = udiv i32 %u_dvnd, %u_dvsr
102127 // ; %tmp4 = xor i32 %q_mag, %q_sgn
103128 // ; %q = sub i32 %tmp4, %q_sgn
104 Value *Tmp = Builder.CreateAShr(Dividend, ThirtyOne);
105 Value *Tmp1 = Builder.CreateAShr(Divisor, ThirtyOne);
129 Value *Tmp = Builder.CreateAShr(Dividend, Shift);
130 Value *Tmp1 = Builder.CreateAShr(Divisor, Shift);
106131 Value *Tmp2 = Builder.CreateXor(Tmp, Dividend);
107132 Value *U_Dvnd = Builder.CreateSub(Tmp2, Tmp);
108133 Value *Tmp3 = Builder.CreateXor(Tmp1, Divisor);
118143 return Q;
119144 }
120145
121 /// Generates code to divide two unsigned scalar 32-bit integers. Returns the
122 /// quotient, rounded towards 0. Builder's insert point should be pointing where
123 /// the caller wants code generated, e.g. at the udiv instruction.
146 /// Generates code to divide two unsigned scalar 32-bit or 64-bit integers.
147 /// Returns the quotient, rounded towards 0. Builder's insert point should
148 /// point where the caller wants code generated, e.g. at the udiv instruction.
124149 static Value *generateUnsignedDivisionCode(Value *Dividend, Value *Divisor,
125150 IRBuilder<> &Builder) {
126151 // The basic algorithm can be found in the compiler-rt project's
128153 // that's been hand-tuned to lessen the amount of control flow involved.
129154
130155 // Some helper values
131 IntegerType *I32Ty = Builder.getInt32Ty();
132
133 ConstantInt *Zero = Builder.getInt32(0);
134 ConstantInt *One = Builder.getInt32(1);
135 ConstantInt *ThirtyOne = Builder.getInt32(31);
136 ConstantInt *NegOne = ConstantInt::getSigned(I32Ty, -1);
137 ConstantInt *True = Builder.getTrue();
156 IntegerType *DivTy = cast(Dividend->getType());
157 unsigned BitWidth = DivTy->getBitWidth();
158
159 ConstantInt *Zero;
160 ConstantInt *One;
161 ConstantInt *NegOne;
162 ConstantInt *MSB;
163
164 if (BitWidth == 64) {
165 Zero = Builder.getInt64(0);
166 One = Builder.getInt64(1);
167 NegOne = ConstantInt::getSigned(DivTy, -1);
168 MSB = Builder.getInt64(63);
169 } else {
170 assert(BitWidth == 32 && "Unexpected bit width");
171 Zero = Builder.getInt32(0);
172 One = Builder.getInt32(1);
173 NegOne = ConstantInt::getSigned(DivTy, -1);
174 MSB = Builder.getInt32(31);
175 }
176
177 ConstantInt *True = Builder.getTrue();
138178
139179 BasicBlock *IBB = Builder.GetInsertBlock();
140180 Function *F = IBB->getParent();
141 Function *CTLZi32 = Intrinsic::getDeclaration(F->getParent(), Intrinsic::ctlz,
142 I32Ty);
181 Function *CTLZ = Intrinsic::getDeclaration(F->getParent(), Intrinsic::ctlz,
182 DivTy);
143183
144184 // Our CFG is going to look like:
145185 // +---------------------+
189229 // We'll be overwriting the terminator to insert our extra blocks
190230 SpecialCases->getTerminator()->eraseFromParent();
191231
232 // Same instructions are generated for both i32 (msb 31) and i64 (msb 63).
233
192234 // First off, check for special cases: dividend or divisor is zero, divisor
193235 // is greater than dividend, and divisor is 1.
194236 // ; special-cases:
208250 Value *Ret0_1 = Builder.CreateICmpEQ(Divisor, Zero);
209251 Value *Ret0_2 = Builder.CreateICmpEQ(Dividend, Zero);
210252 Value *Ret0_3 = Builder.CreateOr(Ret0_1, Ret0_2);
211 Value *Tmp0 = Builder.CreateCall2(CTLZi32, Divisor, True);
212 Value *Tmp1 = Builder.CreateCall2(CTLZi32, Dividend, True);
253 Value *Tmp0 = Builder.CreateCall2(CTLZ, Divisor, True);
254 Value *Tmp1 = Builder.CreateCall2(CTLZ, Dividend, True);
213255 Value *SR = Builder.CreateSub(Tmp0, Tmp1);
214 Value *Ret0_4 = Builder.CreateICmpUGT(SR, ThirtyOne);
256 Value *Ret0_4 = Builder.CreateICmpUGT(SR, MSB);
215257 Value *Ret0 = Builder.CreateOr(Ret0_3, Ret0_4);
216 Value *RetDividend = Builder.CreateICmpEQ(SR, ThirtyOne);
258 Value *RetDividend = Builder.CreateICmpEQ(SR, MSB);
217259 Value *RetVal = Builder.CreateSelect(Ret0, Zero, Dividend);
218260 Value *EarlyRet = Builder.CreateOr(Ret0, RetDividend);
219261 Builder.CreateCondBr(EarlyRet, End, BB1);
226268 // ; br i1 %skipLoop, label %loop-exit, label %preheader
227269 Builder.SetInsertPoint(BB1);
228270 Value *SR_1 = Builder.CreateAdd(SR, One);
229 Value *Tmp2 = Builder.CreateSub(ThirtyOne, SR);
271 Value *Tmp2 = Builder.CreateSub(MSB, SR);
230272 Value *Q = Builder.CreateShl(Dividend, Tmp2);
231273 Value *SkipLoop = Builder.CreateICmpEQ(SR_1, Zero);
232274 Builder.CreateCondBr(SkipLoop, LoopExit, Preheader);
259301 // ; %tmp12 = icmp eq i32 %sr_2, 0
260302 // ; br i1 %tmp12, label %loop-exit, label %do-while
261303 Builder.SetInsertPoint(DoWhile);
262 PHINode *Carry_1 = Builder.CreatePHI(I32Ty, 2);
263 PHINode *SR_3 = Builder.CreatePHI(I32Ty, 2);
264 PHINode *R_1 = Builder.CreatePHI(I32Ty, 2);
265 PHINode *Q_2 = Builder.CreatePHI(I32Ty, 2);
304 PHINode *Carry_1 = Builder.CreatePHI(DivTy, 2);
305 PHINode *SR_3 = Builder.CreatePHI(DivTy, 2);
306 PHINode *R_1 = Builder.CreatePHI(DivTy, 2);
307 PHINode *Q_2 = Builder.CreatePHI(DivTy, 2);
266308 Value *Tmp5 = Builder.CreateShl(R_1, One);
267 Value *Tmp6 = Builder.CreateLShr(Q_2, ThirtyOne);
309 Value *Tmp6 = Builder.CreateLShr(Q_2, MSB);
268310 Value *Tmp7 = Builder.CreateOr(Tmp5, Tmp6);
269311 Value *Tmp8 = Builder.CreateShl(Q_2, One);
270312 Value *Q_1 = Builder.CreateOr(Carry_1, Tmp8);
271313 Value *Tmp9 = Builder.CreateSub(Tmp4, Tmp7);
272 Value *Tmp10 = Builder.CreateAShr(Tmp9, 31);
314 Value *Tmp10 = Builder.CreateAShr(Tmp9, MSB);
273315 Value *Carry = Builder.CreateAnd(Tmp10, One);
274316 Value *Tmp11 = Builder.CreateAnd(Tmp10, Divisor);
275317 Value *R = Builder.CreateSub(Tmp7, Tmp11);
284326 // ; %q_4 = or i32 %carry_2, %tmp13
285327 // ; br label %end
286328 Builder.SetInsertPoint(LoopExit);
287 PHINode *Carry_2 = Builder.CreatePHI(I32Ty, 2);
288 PHINode *Q_3 = Builder.CreatePHI(I32Ty, 2);
329 PHINode *Carry_2 = Builder.CreatePHI(DivTy, 2);
330 PHINode *Q_3 = Builder.CreatePHI(DivTy, 2);
289331 Value *Tmp13 = Builder.CreateShl(Q_3, One);
290332 Value *Q_4 = Builder.CreateOr(Carry_2, Tmp13);
291333 Builder.CreateBr(End);
294336 // ; %q_5 = phi i32 [ %q_4, %loop-exit ], [ %retVal, %special-cases ]
295337 // ; ret i32 %q_5
296338 Builder.SetInsertPoint(End, End->begin());
297 PHINode *Q_5 = Builder.CreatePHI(I32Ty, 2);
339 PHINode *Q_5 = Builder.CreatePHI(DivTy, 2);
298340
299341 // Populate the Phis, since all values have now been created. Our Phis were:
300342 // ; %carry_1 = phi i32 [ 0, %preheader ], [ %carry, %do-while ]
325367 /// Generate code to calculate the remainder of two integers, replacing Rem with
326368 /// the generated code. This currently generates code using the udiv expansion,
327369 /// but future work includes generating more specialized code, e.g. when more
328 /// information about the operands are known. Currently only implements 32bit
329 /// scalar division (due to udiv's limitation), but future work is removing this
330 /// limitation.
370 /// information about the operands are known. Implements both 32bit and 64bit
371 /// scalar division.
331372 ///
332373 /// @brief Replace Rem with generated code.
333374 bool llvm::expandRemainder(BinaryOperator *Rem) {
337378
338379 IRBuilder<> Builder(Rem);
339380
381 Type *RemTy = Rem->getType();
382 if (RemTy->isVectorTy())
383 llvm_unreachable("Div over vectors not supported");
384
385 unsigned RemTyBitWidth = RemTy->getIntegerBitWidth();
386
387 if (RemTyBitWidth != 32 && RemTyBitWidth != 64)
388 llvm_unreachable("Div of bitwidth other than 32 or 64 not supported");
389
340390 // First prepare the sign if it's a signed remainder
341391 if (Rem->getOpcode() == Instruction::SRem) {
342392 Value *Remainder = generateSignedRemainderCode(Rem->getOperand(0),
375425 /// Generate code to divide two integers, replacing Div with the generated
376426 /// code. This currently generates code similarly to compiler-rt's
377427 /// implementations, but future work includes generating more specialized code
378 /// when more information about the operands are known. Currently only
379 /// implements 32bit scalar division, but future work is removing this
380 /// limitation.
428 /// when more information about the operands are known. Implements both
429 /// 32bit and 64bit scalar division.
381430 ///
382431 /// @brief Replace Div with generated code.
383432 bool llvm::expandDivision(BinaryOperator *Div) {
387436
388437 IRBuilder<> Builder(Div);
389438
390 if (Div->getType()->isVectorTy())
439 Type *DivTy = Div->getType();
440 if (DivTy->isVectorTy())
391441 llvm_unreachable("Div over vectors not supported");
442
443 unsigned DivTyBitWidth = DivTy->getIntegerBitWidth();
444
445 if (DivTyBitWidth != 32 && DivTyBitWidth != 64)
446 llvm_unreachable("Div of bitwidth other than 32 or 64 not supported");
392447
393448 // First prepare the sign if it's a signed division
394449 if (Div->getOpcode() == Instruction::SDiv) {
442497 if (RemTyBitWidth == 32)
443498 return expandRemainder(Rem);
444499
445 // If bitwidth smaller than 32 extend inputs, truncate output and proceed
500 // If bitwidth smaller than 32 extend inputs, extend output and proceed
446501 // with 32 bit division.
447502 IRBuilder<> Builder(Rem);
448503
470525 return expandRemainder(cast(ExtRem));
471526 }
472527
528 /// Generate code to compute the remainder of two integers of bitwidth up to
529 /// 64 bits. Uses the above routines and extends the inputs/truncates the
530 /// outputs to operate in 64 bits.
531 ///
532 /// @brief Replace Rem with emulation code.
533 bool llvm::expandRemainderUpTo64Bits(BinaryOperator *Rem) {
534 assert((Rem->getOpcode() == Instruction::SRem ||
535 Rem->getOpcode() == Instruction::URem) &&
536 "Trying to expand remainder from a non-remainder function");
537
538 Type *RemTy = Rem->getType();
539 if (RemTy->isVectorTy())
540 llvm_unreachable("Div over vectors not supported");
541
542 unsigned RemTyBitWidth = RemTy->getIntegerBitWidth();
543
544 if (RemTyBitWidth > 64)
545 llvm_unreachable("Div of bitwidth greater than 64 not supported");
546
547 if (RemTyBitWidth == 64)
548 return expandRemainder(Rem);
549
550 // If bitwidth smaller than 64 extend inputs, extend output and proceed
551 // with 64 bit division.
552 IRBuilder<> Builder(Rem);
553
554 Value *ExtDividend;
555 Value *ExtDivisor;
556 Value *ExtRem;
557 Value *Trunc;
558 Type *Int64Ty = Builder.getInt64Ty();
559
560 if (Rem->getOpcode() == Instruction::SRem) {
561 ExtDividend = Builder.CreateSExt(Rem->getOperand(0), Int64Ty);
562 ExtDivisor = Builder.CreateSExt(Rem->getOperand(1), Int64Ty);
563 ExtRem = Builder.CreateSRem(ExtDividend, ExtDivisor);
564 } else {
565 ExtDividend = Builder.CreateZExt(Rem->getOperand(0), Int64Ty);
566 ExtDivisor = Builder.CreateZExt(Rem->getOperand(1), Int64Ty);
567 ExtRem = Builder.CreateURem(ExtDividend, ExtDivisor);
568 }
569 Trunc = Builder.CreateTrunc(ExtRem, RemTy);
570
571 Rem->replaceAllUsesWith(Trunc);
572 Rem->dropAllReferences();
573 Rem->eraseFromParent();
574
575 return expandRemainder(cast(ExtRem));
576 }
473577
474578 /// Generate code to divide two integers of bitwidth up to 32 bits. Uses the
475579 /// above routines and extends the inputs/truncates the outputs to operate
494598 if (DivTyBitWidth == 32)
495599 return expandDivision(Div);
496600
497 // If bitwidth smaller than 32 extend inputs, truncate output and proceed
601 // If bitwidth smaller than 32 extend inputs, extend output and proceed
498602 // with 32 bit division.
499603 IRBuilder<> Builder(Div);
500604
521625
522626 return expandDivision(cast(ExtDiv));
523627 }
628
629 /// Generate code to divide two integers of bitwidth up to 64 bits. Uses the
630 /// above routines and extends the inputs/truncates the outputs to operate
631 /// in 64 bits.
632 ///
633 /// @brief Replace Div with emulation code.
634 bool llvm::expandDivisionUpTo64Bits(BinaryOperator *Div) {
635 assert((Div->getOpcode() == Instruction::SDiv ||
636 Div->getOpcode() == Instruction::UDiv) &&
637 "Trying to expand division from a non-division function");
638
639 Type *DivTy = Div->getType();
640 if (DivTy->isVectorTy())
641 llvm_unreachable("Div over vectors not supported");
642
643 unsigned DivTyBitWidth = DivTy->getIntegerBitWidth();
644
645 if (DivTyBitWidth > 64)
646 llvm_unreachable("Div of bitwidth greater than 64 not supported");
647
648 if (DivTyBitWidth == 64)
649 return expandDivision(Div);
650
651 // If bitwidth smaller than 64 extend inputs, extend output and proceed
652 // with 64 bit division.
653 IRBuilder<> Builder(Div);
654
655 Value *ExtDividend;
656 Value *ExtDivisor;
657 Value *ExtDiv;
658 Value *Trunc;
659 Type *Int64Ty = Builder.getInt64Ty();
660
661 if (Div->getOpcode() == Instruction::SDiv) {
662 ExtDividend = Builder.CreateSExt(Div->getOperand(0), Int64Ty);
663 ExtDivisor = Builder.CreateSExt(Div->getOperand(1), Int64Ty);
664 ExtDiv = Builder.CreateSDiv(ExtDividend, ExtDivisor);
665 } else {
666 ExtDividend = Builder.CreateZExt(Div->getOperand(0), Int64Ty);
667 ExtDivisor = Builder.CreateZExt(Div->getOperand(1), Int64Ty);
668 ExtDiv = Builder.CreateUDiv(ExtDividend, ExtDivisor);
669 }
670 Trunc = Builder.CreateTrunc(ExtDiv, DivTy);
671
672 Div->replaceAllUsesWith(Trunc);
673 Div->dropAllReferences();
674 Div->eraseFromParent();
675
676 return expandDivision(cast(ExtDiv));
677 }
1818
1919 namespace {
2020
21
2122 TEST(IntegerDivision, SDiv) {
2223 LLVMContext &C(getGlobalContext());
2324 Module M("test division", C);
138139 EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
139140 }
140141
141 }
142
143 TEST(IntegerDivision, SDiv64) {
144 LLVMContext &C(getGlobalContext());
145 Module M("test division", C);
146 IRBuilder<> Builder(C);
147
148 SmallVector ArgTys(2, Builder.getInt64Ty());
149 Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
150 ArgTys, false),
151 GlobalValue::ExternalLinkage, "F", &M);
152 assert(F->getArgumentList().size() == 2);
153
154 BasicBlock *BB = BasicBlock::Create(C, "", F);
155 Builder.SetInsertPoint(BB);
156
157 Function::arg_iterator AI = F->arg_begin();
158 Value *A = AI++;
159 Value *B = AI++;
160
161 Value *Div = Builder.CreateSDiv(A, B);
162 EXPECT_TRUE(BB->front().getOpcode() == Instruction::SDiv);
163
164 Value *Ret = Builder.CreateRet(Div);
165
166 expandDivision(cast(Div));
167 EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr);
168
169 Instruction* Quotient = dyn_cast(cast(Ret)->getOperand(0));
170 EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::Sub);
171 }
172
173 TEST(IntegerDivision, UDiv64) {
174 LLVMContext &C(getGlobalContext());
175 Module M("test division", C);
176 IRBuilder<> Builder(C);
177
178 SmallVector ArgTys(2, Builder.getInt64Ty());
179 Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
180 ArgTys, false),
181 GlobalValue::ExternalLinkage, "F", &M);
182 assert(F->getArgumentList().size() == 2);
183
184 BasicBlock *BB = BasicBlock::Create(C, "", F);
185 Builder.SetInsertPoint(BB);
186
187 Function::arg_iterator AI = F->arg_begin();
188 Value *A = AI++;
189 Value *B = AI++;
190
191 Value *Div = Builder.CreateUDiv(A, B);
192 EXPECT_TRUE(BB->front().getOpcode() == Instruction::UDiv);
193
194 Value *Ret = Builder.CreateRet(Div);
195
196 expandDivision(cast(Div));
197 EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp);
198
199 Instruction* Quotient = dyn_cast(cast(Ret)->getOperand(0));
200 EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::PHI);
201 }
202
203 TEST(IntegerDivision, SRem64) {
204 LLVMContext &C(getGlobalContext());
205 Module M("test remainder", C);
206 IRBuilder<> Builder(C);
207
208 SmallVector ArgTys(2, Builder.getInt64Ty());
209 Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
210 ArgTys, false),
211 GlobalValue::ExternalLinkage, "F", &M);
212 assert(F->getArgumentList().size() == 2);
213
214 BasicBlock *BB = BasicBlock::Create(C, "", F);
215 Builder.SetInsertPoint(BB);
216
217 Function::arg_iterator AI = F->arg_begin();
218 Value *A = AI++;
219 Value *B = AI++;
220
221 Value *Rem = Builder.CreateSRem(A, B);
222 EXPECT_TRUE(BB->front().getOpcode() == Instruction::SRem);
223
224 Value *Ret = Builder.CreateRet(Rem);
225
226 expandRemainder(cast(Rem));
227 EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr);
228
229 Instruction* Remainder = dyn_cast(cast(Ret)->getOperand(0));
230 EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
231 }
232
233 TEST(IntegerDivision, URem64) {
234 LLVMContext &C(getGlobalContext());
235 Module M("test remainder", C);
236 IRBuilder<> Builder(C);
237
238 SmallVector ArgTys(2, Builder.getInt64Ty());
239 Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
240 ArgTys, false),
241 GlobalValue::ExternalLinkage, "F", &M);
242 assert(F->getArgumentList().size() == 2);
243
244 BasicBlock *BB = BasicBlock::Create(C, "", F);
245 Builder.SetInsertPoint(BB);
246
247 Function::arg_iterator AI = F->arg_begin();
248 Value *A = AI++;
249 Value *B = AI++;
250
251 Value *Rem = Builder.CreateURem(A, B);
252 EXPECT_TRUE(BB->front().getOpcode() == Instruction::URem);
253
254 Value *Ret = Builder.CreateRet(Rem);
255
256 expandRemainder(cast(Rem));
257 EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp);
258
259 Instruction* Remainder = dyn_cast(cast(Ret)->getOperand(0));
260 EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
261 }
262
263 }