13861d79fSDimitry Andric //===-- IntegerDivision.cpp - Expand integer division ---------------------===//
23861d79fSDimitry Andric //
33861d79fSDimitry Andric //                     The LLVM Compiler Infrastructure
43861d79fSDimitry Andric //
53861d79fSDimitry Andric // This file is distributed under the University of Illinois Open Source
63861d79fSDimitry Andric // License. See LICENSE.TXT for details.
73861d79fSDimitry Andric //
83861d79fSDimitry Andric //===----------------------------------------------------------------------===//
93861d79fSDimitry Andric //
1091bc56edSDimitry Andric // This file contains an implementation of 32bit and 64bit scalar integer
1191bc56edSDimitry Andric // division for targets that don't have native support. It's largely derived
1291bc56edSDimitry Andric // from compiler-rt's implementations of __udivsi3 and __udivmoddi4,
1391bc56edSDimitry Andric // but hand-tuned for targets that prefer less control flow.
143861d79fSDimitry Andric //
153861d79fSDimitry Andric //===----------------------------------------------------------------------===//
163861d79fSDimitry Andric 
173861d79fSDimitry Andric #include "llvm/Transforms/Utils/IntegerDivision.h"
18139f7f9bSDimitry Andric #include "llvm/IR/Function.h"
19139f7f9bSDimitry Andric #include "llvm/IR/IRBuilder.h"
20139f7f9bSDimitry Andric #include "llvm/IR/Instructions.h"
21139f7f9bSDimitry Andric #include "llvm/IR/Intrinsics.h"
2291bc56edSDimitry Andric #include <utility>
233861d79fSDimitry Andric 
243861d79fSDimitry Andric using namespace llvm;
253861d79fSDimitry Andric 
2691bc56edSDimitry Andric #define DEBUG_TYPE "integer-division"
2791bc56edSDimitry Andric 
283861d79fSDimitry Andric /// Generate code to compute the remainder of two signed integers. Returns the
293861d79fSDimitry Andric /// remainder, which will have the sign of the dividend. Builder's insert point
303861d79fSDimitry Andric /// should be pointing where the caller wants code generated, e.g. at the srem
313861d79fSDimitry Andric /// instruction. This will generate a urem in the process, and Builder's insert
323861d79fSDimitry Andric /// point will be pointing at the uren (if present, i.e. not folded), ready to
333861d79fSDimitry Andric /// be expanded if the user wishes
generateSignedRemainderCode(Value * Dividend,Value * Divisor,IRBuilder<> & Builder)343861d79fSDimitry Andric static Value *generateSignedRemainderCode(Value *Dividend, Value *Divisor,
353861d79fSDimitry Andric                                           IRBuilder<> &Builder) {
3691bc56edSDimitry Andric   unsigned BitWidth = Dividend->getType()->getIntegerBitWidth();
3791bc56edSDimitry Andric   ConstantInt *Shift;
3891bc56edSDimitry Andric 
3991bc56edSDimitry Andric   if (BitWidth == 64) {
4091bc56edSDimitry Andric     Shift = Builder.getInt64(63);
4191bc56edSDimitry Andric   } else {
4291bc56edSDimitry Andric     assert(BitWidth == 32 && "Unexpected bit width");
4391bc56edSDimitry Andric     Shift = Builder.getInt32(31);
4491bc56edSDimitry Andric   }
4591bc56edSDimitry Andric 
4691bc56edSDimitry Andric   // Following instructions are generated for both i32 (shift 31) and
4791bc56edSDimitry Andric   // i64 (shift 63).
483861d79fSDimitry Andric 
493861d79fSDimitry Andric   // ;   %dividend_sgn = ashr i32 %dividend, 31
503861d79fSDimitry Andric   // ;   %divisor_sgn  = ashr i32 %divisor, 31
513861d79fSDimitry Andric   // ;   %dvd_xor      = xor i32 %dividend, %dividend_sgn
523861d79fSDimitry Andric   // ;   %dvs_xor      = xor i32 %divisor, %divisor_sgn
533861d79fSDimitry Andric   // ;   %u_dividend   = sub i32 %dvd_xor, %dividend_sgn
543861d79fSDimitry Andric   // ;   %u_divisor    = sub i32 %dvs_xor, %divisor_sgn
553861d79fSDimitry Andric   // ;   %urem         = urem i32 %dividend, %divisor
563861d79fSDimitry Andric   // ;   %xored        = xor i32 %urem, %dividend_sgn
573861d79fSDimitry Andric   // ;   %srem         = sub i32 %xored, %dividend_sgn
5891bc56edSDimitry Andric   Value *DividendSign = Builder.CreateAShr(Dividend, Shift);
5991bc56edSDimitry Andric   Value *DivisorSign  = Builder.CreateAShr(Divisor, Shift);
603861d79fSDimitry Andric   Value *DvdXor       = Builder.CreateXor(Dividend, DividendSign);
613861d79fSDimitry Andric   Value *DvsXor       = Builder.CreateXor(Divisor, DivisorSign);
623861d79fSDimitry Andric   Value *UDividend    = Builder.CreateSub(DvdXor, DividendSign);
633861d79fSDimitry Andric   Value *UDivisor     = Builder.CreateSub(DvsXor, DivisorSign);
643861d79fSDimitry Andric   Value *URem         = Builder.CreateURem(UDividend, UDivisor);
653861d79fSDimitry Andric   Value *Xored        = Builder.CreateXor(URem, DividendSign);
663861d79fSDimitry Andric   Value *SRem         = Builder.CreateSub(Xored, DividendSign);
673861d79fSDimitry Andric 
683861d79fSDimitry Andric   if (Instruction *URemInst = dyn_cast<Instruction>(URem))
693861d79fSDimitry Andric     Builder.SetInsertPoint(URemInst);
703861d79fSDimitry Andric 
713861d79fSDimitry Andric   return SRem;
723861d79fSDimitry Andric }
733861d79fSDimitry Andric 
743861d79fSDimitry Andric 
753861d79fSDimitry Andric /// Generate code to compute the remainder of two unsigned integers. Returns the
763861d79fSDimitry Andric /// remainder. Builder's insert point should be pointing where the caller wants
773861d79fSDimitry Andric /// code generated, e.g. at the urem instruction. This will generate a udiv in
783861d79fSDimitry Andric /// the process, and Builder's insert point will be pointing at the udiv (if
793861d79fSDimitry Andric /// present, i.e. not folded), ready to be expanded if the user wishes
generatedUnsignedRemainderCode(Value * Dividend,Value * Divisor,IRBuilder<> & Builder)803861d79fSDimitry Andric static Value *generatedUnsignedRemainderCode(Value *Dividend, Value *Divisor,
813861d79fSDimitry Andric                                              IRBuilder<> &Builder) {
823861d79fSDimitry Andric   // Remainder = Dividend - Quotient*Divisor
833861d79fSDimitry Andric 
8491bc56edSDimitry Andric   // Following instructions are generated for both i32 and i64
8591bc56edSDimitry Andric 
863861d79fSDimitry Andric   // ;   %quotient  = udiv i32 %dividend, %divisor
873861d79fSDimitry Andric   // ;   %product   = mul i32 %divisor, %quotient
883861d79fSDimitry Andric   // ;   %remainder = sub i32 %dividend, %product
893861d79fSDimitry Andric   Value *Quotient  = Builder.CreateUDiv(Dividend, Divisor);
903861d79fSDimitry Andric   Value *Product   = Builder.CreateMul(Divisor, Quotient);
913861d79fSDimitry Andric   Value *Remainder = Builder.CreateSub(Dividend, Product);
923861d79fSDimitry Andric 
933861d79fSDimitry Andric   if (Instruction *UDiv = dyn_cast<Instruction>(Quotient))
943861d79fSDimitry Andric     Builder.SetInsertPoint(UDiv);
953861d79fSDimitry Andric 
963861d79fSDimitry Andric   return Remainder;
973861d79fSDimitry Andric }
983861d79fSDimitry Andric 
993861d79fSDimitry Andric /// Generate code to divide two signed integers. Returns the quotient, rounded
1003861d79fSDimitry Andric /// towards 0. Builder's insert point should be pointing where the caller wants
1013861d79fSDimitry Andric /// code generated, e.g. at the sdiv instruction. This will generate a udiv in
1023861d79fSDimitry Andric /// the process, and Builder's insert point will be pointing at the udiv (if
1033861d79fSDimitry Andric /// present, i.e. not folded), ready to be expanded if the user wishes.
generateSignedDivisionCode(Value * Dividend,Value * Divisor,IRBuilder<> & Builder)1043861d79fSDimitry Andric static Value *generateSignedDivisionCode(Value *Dividend, Value *Divisor,
1053861d79fSDimitry Andric                                          IRBuilder<> &Builder) {
10691bc56edSDimitry Andric   // Implementation taken from compiler-rt's __divsi3 and __divdi3
1073861d79fSDimitry Andric 
10891bc56edSDimitry Andric   unsigned BitWidth = Dividend->getType()->getIntegerBitWidth();
10991bc56edSDimitry Andric   ConstantInt *Shift;
11091bc56edSDimitry Andric 
11191bc56edSDimitry Andric   if (BitWidth == 64) {
11291bc56edSDimitry Andric     Shift = Builder.getInt64(63);
11391bc56edSDimitry Andric   } else {
11491bc56edSDimitry Andric     assert(BitWidth == 32 && "Unexpected bit width");
11591bc56edSDimitry Andric     Shift = Builder.getInt32(31);
11691bc56edSDimitry Andric   }
11791bc56edSDimitry Andric 
11891bc56edSDimitry Andric   // Following instructions are generated for both i32 (shift 31) and
11991bc56edSDimitry Andric   // i64 (shift 63).
1203861d79fSDimitry Andric 
1213861d79fSDimitry Andric   // ;   %tmp    = ashr i32 %dividend, 31
1223861d79fSDimitry Andric   // ;   %tmp1   = ashr i32 %divisor, 31
1233861d79fSDimitry Andric   // ;   %tmp2   = xor i32 %tmp, %dividend
1243861d79fSDimitry Andric   // ;   %u_dvnd = sub nsw i32 %tmp2, %tmp
1253861d79fSDimitry Andric   // ;   %tmp3   = xor i32 %tmp1, %divisor
1263861d79fSDimitry Andric   // ;   %u_dvsr = sub nsw i32 %tmp3, %tmp1
1273861d79fSDimitry Andric   // ;   %q_sgn  = xor i32 %tmp1, %tmp
1283861d79fSDimitry Andric   // ;   %q_mag  = udiv i32 %u_dvnd, %u_dvsr
1293861d79fSDimitry Andric   // ;   %tmp4   = xor i32 %q_mag, %q_sgn
1303861d79fSDimitry Andric   // ;   %q      = sub i32 %tmp4, %q_sgn
13191bc56edSDimitry Andric   Value *Tmp    = Builder.CreateAShr(Dividend, Shift);
13291bc56edSDimitry Andric   Value *Tmp1   = Builder.CreateAShr(Divisor, Shift);
1333861d79fSDimitry Andric   Value *Tmp2   = Builder.CreateXor(Tmp, Dividend);
1343861d79fSDimitry Andric   Value *U_Dvnd = Builder.CreateSub(Tmp2, Tmp);
1353861d79fSDimitry Andric   Value *Tmp3   = Builder.CreateXor(Tmp1, Divisor);
1363861d79fSDimitry Andric   Value *U_Dvsr = Builder.CreateSub(Tmp3, Tmp1);
1373861d79fSDimitry Andric   Value *Q_Sgn  = Builder.CreateXor(Tmp1, Tmp);
1383861d79fSDimitry Andric   Value *Q_Mag  = Builder.CreateUDiv(U_Dvnd, U_Dvsr);
1393861d79fSDimitry Andric   Value *Tmp4   = Builder.CreateXor(Q_Mag, Q_Sgn);
1403861d79fSDimitry Andric   Value *Q      = Builder.CreateSub(Tmp4, Q_Sgn);
1413861d79fSDimitry Andric 
1423861d79fSDimitry Andric   if (Instruction *UDiv = dyn_cast<Instruction>(Q_Mag))
1433861d79fSDimitry Andric     Builder.SetInsertPoint(UDiv);
1443861d79fSDimitry Andric 
1453861d79fSDimitry Andric   return Q;
1463861d79fSDimitry Andric }
1473861d79fSDimitry Andric 
14891bc56edSDimitry Andric /// Generates code to divide two unsigned scalar 32-bit or 64-bit integers.
14991bc56edSDimitry Andric /// Returns the quotient, rounded towards 0. Builder's insert point should
15091bc56edSDimitry Andric /// point where the caller wants code generated, e.g. at the udiv instruction.
generateUnsignedDivisionCode(Value * Dividend,Value * Divisor,IRBuilder<> & Builder)1513861d79fSDimitry Andric static Value *generateUnsignedDivisionCode(Value *Dividend, Value *Divisor,
1523861d79fSDimitry Andric                                            IRBuilder<> &Builder) {
1533861d79fSDimitry Andric   // The basic algorithm can be found in the compiler-rt project's
1543861d79fSDimitry Andric   // implementation of __udivsi3.c. Here, we do a lower-level IR based approach
1553861d79fSDimitry Andric   // that's been hand-tuned to lessen the amount of control flow involved.
1563861d79fSDimitry Andric 
1573861d79fSDimitry Andric   // Some helper values
15891bc56edSDimitry Andric   IntegerType *DivTy = cast<IntegerType>(Dividend->getType());
15991bc56edSDimitry Andric   unsigned BitWidth = DivTy->getBitWidth();
1603861d79fSDimitry Andric 
16191bc56edSDimitry Andric   ConstantInt *Zero;
16291bc56edSDimitry Andric   ConstantInt *One;
16391bc56edSDimitry Andric   ConstantInt *NegOne;
16491bc56edSDimitry Andric   ConstantInt *MSB;
16591bc56edSDimitry Andric 
16691bc56edSDimitry Andric   if (BitWidth == 64) {
16791bc56edSDimitry Andric     Zero      = Builder.getInt64(0);
16891bc56edSDimitry Andric     One       = Builder.getInt64(1);
16991bc56edSDimitry Andric     NegOne    = ConstantInt::getSigned(DivTy, -1);
17091bc56edSDimitry Andric     MSB       = Builder.getInt64(63);
17191bc56edSDimitry Andric   } else {
17291bc56edSDimitry Andric     assert(BitWidth == 32 && "Unexpected bit width");
17391bc56edSDimitry Andric     Zero      = Builder.getInt32(0);
17491bc56edSDimitry Andric     One       = Builder.getInt32(1);
17591bc56edSDimitry Andric     NegOne    = ConstantInt::getSigned(DivTy, -1);
17691bc56edSDimitry Andric     MSB       = Builder.getInt32(31);
17791bc56edSDimitry Andric   }
17891bc56edSDimitry Andric 
1793861d79fSDimitry Andric   ConstantInt *True = Builder.getTrue();
1803861d79fSDimitry Andric 
1813861d79fSDimitry Andric   BasicBlock *IBB = Builder.GetInsertBlock();
1823861d79fSDimitry Andric   Function *F = IBB->getParent();
18391bc56edSDimitry Andric   Function *CTLZ = Intrinsic::getDeclaration(F->getParent(), Intrinsic::ctlz,
18491bc56edSDimitry Andric                                              DivTy);
1853861d79fSDimitry Andric 
1863861d79fSDimitry Andric   // Our CFG is going to look like:
1873861d79fSDimitry Andric   // +---------------------+
1883861d79fSDimitry Andric   // | special-cases       |
1893861d79fSDimitry Andric   // |   ...               |
1903861d79fSDimitry Andric   // +---------------------+
1913861d79fSDimitry Andric   //  |       |
1923861d79fSDimitry Andric   //  |   +----------+
1933861d79fSDimitry Andric   //  |   |  bb1     |
1943861d79fSDimitry Andric   //  |   |  ...     |
1953861d79fSDimitry Andric   //  |   +----------+
1963861d79fSDimitry Andric   //  |    |      |
1973861d79fSDimitry Andric   //  |    |  +------------+
1983861d79fSDimitry Andric   //  |    |  |  preheader |
1993861d79fSDimitry Andric   //  |    |  |  ...       |
2003861d79fSDimitry Andric   //  |    |  +------------+
2013861d79fSDimitry Andric   //  |    |      |
2023861d79fSDimitry Andric   //  |    |      |      +---+
2033861d79fSDimitry Andric   //  |    |      |      |   |
2043861d79fSDimitry Andric   //  |    |  +------------+ |
2053861d79fSDimitry Andric   //  |    |  |  do-while  | |
2063861d79fSDimitry Andric   //  |    |  |  ...       | |
2073861d79fSDimitry Andric   //  |    |  +------------+ |
2083861d79fSDimitry Andric   //  |    |      |      |   |
2093861d79fSDimitry Andric   //  |   +-----------+  +---+
2103861d79fSDimitry Andric   //  |   | loop-exit |
2113861d79fSDimitry Andric   //  |   |  ...      |
2123861d79fSDimitry Andric   //  |   +-----------+
2133861d79fSDimitry Andric   //  |     |
2143861d79fSDimitry Andric   // +-------+
2153861d79fSDimitry Andric   // | ...   |
2163861d79fSDimitry Andric   // | end   |
2173861d79fSDimitry Andric   // +-------+
2183861d79fSDimitry Andric   BasicBlock *SpecialCases = Builder.GetInsertBlock();
2193861d79fSDimitry Andric   SpecialCases->setName(Twine(SpecialCases->getName(), "_udiv-special-cases"));
2203861d79fSDimitry Andric   BasicBlock *End = SpecialCases->splitBasicBlock(Builder.GetInsertPoint(),
2213861d79fSDimitry Andric                                                   "udiv-end");
2223861d79fSDimitry Andric   BasicBlock *LoopExit  = BasicBlock::Create(Builder.getContext(),
2233861d79fSDimitry Andric                                              "udiv-loop-exit", F, End);
2243861d79fSDimitry Andric   BasicBlock *DoWhile   = BasicBlock::Create(Builder.getContext(),
2253861d79fSDimitry Andric                                              "udiv-do-while", F, End);
2263861d79fSDimitry Andric   BasicBlock *Preheader = BasicBlock::Create(Builder.getContext(),
2273861d79fSDimitry Andric                                              "udiv-preheader", F, End);
2283861d79fSDimitry Andric   BasicBlock *BB1       = BasicBlock::Create(Builder.getContext(),
2293861d79fSDimitry Andric                                              "udiv-bb1", F, End);
2303861d79fSDimitry Andric 
2313861d79fSDimitry Andric   // We'll be overwriting the terminator to insert our extra blocks
2323861d79fSDimitry Andric   SpecialCases->getTerminator()->eraseFromParent();
2333861d79fSDimitry Andric 
23491bc56edSDimitry Andric   // Same instructions are generated for both i32 (msb 31) and i64 (msb 63).
23591bc56edSDimitry Andric 
2363861d79fSDimitry Andric   // First off, check for special cases: dividend or divisor is zero, divisor
2373861d79fSDimitry Andric   // is greater than dividend, and divisor is 1.
2383861d79fSDimitry Andric   // ; special-cases:
2393861d79fSDimitry Andric   // ;   %ret0_1      = icmp eq i32 %divisor, 0
2403861d79fSDimitry Andric   // ;   %ret0_2      = icmp eq i32 %dividend, 0
2413861d79fSDimitry Andric   // ;   %ret0_3      = or i1 %ret0_1, %ret0_2
2423861d79fSDimitry Andric   // ;   %tmp0        = tail call i32 @llvm.ctlz.i32(i32 %divisor, i1 true)
2433861d79fSDimitry Andric   // ;   %tmp1        = tail call i32 @llvm.ctlz.i32(i32 %dividend, i1 true)
2443861d79fSDimitry Andric   // ;   %sr          = sub nsw i32 %tmp0, %tmp1
2453861d79fSDimitry Andric   // ;   %ret0_4      = icmp ugt i32 %sr, 31
2463861d79fSDimitry Andric   // ;   %ret0        = or i1 %ret0_3, %ret0_4
2473861d79fSDimitry Andric   // ;   %retDividend = icmp eq i32 %sr, 31
2483861d79fSDimitry Andric   // ;   %retVal      = select i1 %ret0, i32 0, i32 %dividend
2493861d79fSDimitry Andric   // ;   %earlyRet    = or i1 %ret0, %retDividend
2503861d79fSDimitry Andric   // ;   br i1 %earlyRet, label %end, label %bb1
2513861d79fSDimitry Andric   Builder.SetInsertPoint(SpecialCases);
2523861d79fSDimitry Andric   Value *Ret0_1      = Builder.CreateICmpEQ(Divisor, Zero);
2533861d79fSDimitry Andric   Value *Ret0_2      = Builder.CreateICmpEQ(Dividend, Zero);
2543861d79fSDimitry Andric   Value *Ret0_3      = Builder.CreateOr(Ret0_1, Ret0_2);
255ff0cc061SDimitry Andric   Value *Tmp0 = Builder.CreateCall(CTLZ, {Divisor, True});
256ff0cc061SDimitry Andric   Value *Tmp1 = Builder.CreateCall(CTLZ, {Dividend, True});
2573861d79fSDimitry Andric   Value *SR          = Builder.CreateSub(Tmp0, Tmp1);
25891bc56edSDimitry Andric   Value *Ret0_4      = Builder.CreateICmpUGT(SR, MSB);
2593861d79fSDimitry Andric   Value *Ret0        = Builder.CreateOr(Ret0_3, Ret0_4);
26091bc56edSDimitry Andric   Value *RetDividend = Builder.CreateICmpEQ(SR, MSB);
2613861d79fSDimitry Andric   Value *RetVal      = Builder.CreateSelect(Ret0, Zero, Dividend);
2623861d79fSDimitry Andric   Value *EarlyRet    = Builder.CreateOr(Ret0, RetDividend);
2633861d79fSDimitry Andric   Builder.CreateCondBr(EarlyRet, End, BB1);
2643861d79fSDimitry Andric 
2653861d79fSDimitry Andric   // ; bb1:                                             ; preds = %special-cases
2663861d79fSDimitry Andric   // ;   %sr_1     = add i32 %sr, 1
2673861d79fSDimitry Andric   // ;   %tmp2     = sub i32 31, %sr
2683861d79fSDimitry Andric   // ;   %q        = shl i32 %dividend, %tmp2
2693861d79fSDimitry Andric   // ;   %skipLoop = icmp eq i32 %sr_1, 0
2703861d79fSDimitry Andric   // ;   br i1 %skipLoop, label %loop-exit, label %preheader
2713861d79fSDimitry Andric   Builder.SetInsertPoint(BB1);
2723861d79fSDimitry Andric   Value *SR_1     = Builder.CreateAdd(SR, One);
27391bc56edSDimitry Andric   Value *Tmp2     = Builder.CreateSub(MSB, SR);
2743861d79fSDimitry Andric   Value *Q        = Builder.CreateShl(Dividend, Tmp2);
2753861d79fSDimitry Andric   Value *SkipLoop = Builder.CreateICmpEQ(SR_1, Zero);
2763861d79fSDimitry Andric   Builder.CreateCondBr(SkipLoop, LoopExit, Preheader);
2773861d79fSDimitry Andric 
2783861d79fSDimitry Andric   // ; preheader:                                           ; preds = %bb1
2793861d79fSDimitry Andric   // ;   %tmp3 = lshr i32 %dividend, %sr_1
2803861d79fSDimitry Andric   // ;   %tmp4 = add i32 %divisor, -1
2813861d79fSDimitry Andric   // ;   br label %do-while
2823861d79fSDimitry Andric   Builder.SetInsertPoint(Preheader);
2833861d79fSDimitry Andric   Value *Tmp3 = Builder.CreateLShr(Dividend, SR_1);
2843861d79fSDimitry Andric   Value *Tmp4 = Builder.CreateAdd(Divisor, NegOne);
2853861d79fSDimitry Andric   Builder.CreateBr(DoWhile);
2863861d79fSDimitry Andric 
2873861d79fSDimitry Andric   // ; do-while:                                 ; preds = %do-while, %preheader
2883861d79fSDimitry Andric   // ;   %carry_1 = phi i32 [ 0, %preheader ], [ %carry, %do-while ]
2893861d79fSDimitry Andric   // ;   %sr_3    = phi i32 [ %sr_1, %preheader ], [ %sr_2, %do-while ]
2903861d79fSDimitry Andric   // ;   %r_1     = phi i32 [ %tmp3, %preheader ], [ %r, %do-while ]
2913861d79fSDimitry Andric   // ;   %q_2     = phi i32 [ %q, %preheader ], [ %q_1, %do-while ]
2923861d79fSDimitry Andric   // ;   %tmp5  = shl i32 %r_1, 1
2933861d79fSDimitry Andric   // ;   %tmp6  = lshr i32 %q_2, 31
2943861d79fSDimitry Andric   // ;   %tmp7  = or i32 %tmp5, %tmp6
2953861d79fSDimitry Andric   // ;   %tmp8  = shl i32 %q_2, 1
2963861d79fSDimitry Andric   // ;   %q_1   = or i32 %carry_1, %tmp8
2973861d79fSDimitry Andric   // ;   %tmp9  = sub i32 %tmp4, %tmp7
2983861d79fSDimitry Andric   // ;   %tmp10 = ashr i32 %tmp9, 31
2993861d79fSDimitry Andric   // ;   %carry = and i32 %tmp10, 1
3003861d79fSDimitry Andric   // ;   %tmp11 = and i32 %tmp10, %divisor
3013861d79fSDimitry Andric   // ;   %r     = sub i32 %tmp7, %tmp11
3023861d79fSDimitry Andric   // ;   %sr_2  = add i32 %sr_3, -1
3033861d79fSDimitry Andric   // ;   %tmp12 = icmp eq i32 %sr_2, 0
3043861d79fSDimitry Andric   // ;   br i1 %tmp12, label %loop-exit, label %do-while
3053861d79fSDimitry Andric   Builder.SetInsertPoint(DoWhile);
30691bc56edSDimitry Andric   PHINode *Carry_1 = Builder.CreatePHI(DivTy, 2);
30791bc56edSDimitry Andric   PHINode *SR_3    = Builder.CreatePHI(DivTy, 2);
30891bc56edSDimitry Andric   PHINode *R_1     = Builder.CreatePHI(DivTy, 2);
30991bc56edSDimitry Andric   PHINode *Q_2     = Builder.CreatePHI(DivTy, 2);
3103861d79fSDimitry Andric   Value *Tmp5  = Builder.CreateShl(R_1, One);
31191bc56edSDimitry Andric   Value *Tmp6  = Builder.CreateLShr(Q_2, MSB);
3123861d79fSDimitry Andric   Value *Tmp7  = Builder.CreateOr(Tmp5, Tmp6);
3133861d79fSDimitry Andric   Value *Tmp8  = Builder.CreateShl(Q_2, One);
3143861d79fSDimitry Andric   Value *Q_1   = Builder.CreateOr(Carry_1, Tmp8);
3153861d79fSDimitry Andric   Value *Tmp9  = Builder.CreateSub(Tmp4, Tmp7);
31691bc56edSDimitry Andric   Value *Tmp10 = Builder.CreateAShr(Tmp9, MSB);
3173861d79fSDimitry Andric   Value *Carry = Builder.CreateAnd(Tmp10, One);
3183861d79fSDimitry Andric   Value *Tmp11 = Builder.CreateAnd(Tmp10, Divisor);
3193861d79fSDimitry Andric   Value *R     = Builder.CreateSub(Tmp7, Tmp11);
3203861d79fSDimitry Andric   Value *SR_2  = Builder.CreateAdd(SR_3, NegOne);
3213861d79fSDimitry Andric   Value *Tmp12 = Builder.CreateICmpEQ(SR_2, Zero);
3223861d79fSDimitry Andric   Builder.CreateCondBr(Tmp12, LoopExit, DoWhile);
3233861d79fSDimitry Andric 
3243861d79fSDimitry Andric   // ; loop-exit:                                      ; preds = %do-while, %bb1
3253861d79fSDimitry Andric   // ;   %carry_2 = phi i32 [ 0, %bb1 ], [ %carry, %do-while ]
3263861d79fSDimitry Andric   // ;   %q_3     = phi i32 [ %q, %bb1 ], [ %q_1, %do-while ]
3273861d79fSDimitry Andric   // ;   %tmp13 = shl i32 %q_3, 1
3283861d79fSDimitry Andric   // ;   %q_4   = or i32 %carry_2, %tmp13
3293861d79fSDimitry Andric   // ;   br label %end
3303861d79fSDimitry Andric   Builder.SetInsertPoint(LoopExit);
33191bc56edSDimitry Andric   PHINode *Carry_2 = Builder.CreatePHI(DivTy, 2);
33291bc56edSDimitry Andric   PHINode *Q_3     = Builder.CreatePHI(DivTy, 2);
3333861d79fSDimitry Andric   Value *Tmp13 = Builder.CreateShl(Q_3, One);
3343861d79fSDimitry Andric   Value *Q_4   = Builder.CreateOr(Carry_2, Tmp13);
3353861d79fSDimitry Andric   Builder.CreateBr(End);
3363861d79fSDimitry Andric 
3373861d79fSDimitry Andric   // ; end:                                 ; preds = %loop-exit, %special-cases
3383861d79fSDimitry Andric   // ;   %q_5 = phi i32 [ %q_4, %loop-exit ], [ %retVal, %special-cases ]
3393861d79fSDimitry Andric   // ;   ret i32 %q_5
3403861d79fSDimitry Andric   Builder.SetInsertPoint(End, End->begin());
34191bc56edSDimitry Andric   PHINode *Q_5 = Builder.CreatePHI(DivTy, 2);
3423861d79fSDimitry Andric 
3433861d79fSDimitry Andric   // Populate the Phis, since all values have now been created. Our Phis were:
3443861d79fSDimitry Andric   // ;   %carry_1 = phi i32 [ 0, %preheader ], [ %carry, %do-while ]
3453861d79fSDimitry Andric   Carry_1->addIncoming(Zero, Preheader);
3463861d79fSDimitry Andric   Carry_1->addIncoming(Carry, DoWhile);
3473861d79fSDimitry Andric   // ;   %sr_3 = phi i32 [ %sr_1, %preheader ], [ %sr_2, %do-while ]
3483861d79fSDimitry Andric   SR_3->addIncoming(SR_1, Preheader);
3493861d79fSDimitry Andric   SR_3->addIncoming(SR_2, DoWhile);
3503861d79fSDimitry Andric   // ;   %r_1 = phi i32 [ %tmp3, %preheader ], [ %r, %do-while ]
3513861d79fSDimitry Andric   R_1->addIncoming(Tmp3, Preheader);
3523861d79fSDimitry Andric   R_1->addIncoming(R, DoWhile);
3533861d79fSDimitry Andric   // ;   %q_2 = phi i32 [ %q, %preheader ], [ %q_1, %do-while ]
3543861d79fSDimitry Andric   Q_2->addIncoming(Q, Preheader);
3553861d79fSDimitry Andric   Q_2->addIncoming(Q_1, DoWhile);
3563861d79fSDimitry Andric   // ;   %carry_2 = phi i32 [ 0, %bb1 ], [ %carry, %do-while ]
3573861d79fSDimitry Andric   Carry_2->addIncoming(Zero, BB1);
3583861d79fSDimitry Andric   Carry_2->addIncoming(Carry, DoWhile);
3593861d79fSDimitry Andric   // ;   %q_3 = phi i32 [ %q, %bb1 ], [ %q_1, %do-while ]
3603861d79fSDimitry Andric   Q_3->addIncoming(Q, BB1);
3613861d79fSDimitry Andric   Q_3->addIncoming(Q_1, DoWhile);
3623861d79fSDimitry Andric   // ;   %q_5 = phi i32 [ %q_4, %loop-exit ], [ %retVal, %special-cases ]
3633861d79fSDimitry Andric   Q_5->addIncoming(Q_4, LoopExit);
3643861d79fSDimitry Andric   Q_5->addIncoming(RetVal, SpecialCases);
3653861d79fSDimitry Andric 
3663861d79fSDimitry Andric   return Q_5;
3673861d79fSDimitry Andric }
3683861d79fSDimitry Andric 
3693861d79fSDimitry Andric /// Generate code to calculate the remainder of two integers, replacing Rem with
3703861d79fSDimitry Andric /// the generated code. This currently generates code using the udiv expansion,
3713861d79fSDimitry Andric /// but future work includes generating more specialized code, e.g. when more
37291bc56edSDimitry Andric /// information about the operands are known. Implements both 32bit and 64bit
37391bc56edSDimitry Andric /// scalar division.
3743861d79fSDimitry Andric ///
375*4ba319b5SDimitry Andric /// Replace Rem with generated code.
expandRemainder(BinaryOperator * Rem)3763861d79fSDimitry Andric bool llvm::expandRemainder(BinaryOperator *Rem) {
3773861d79fSDimitry Andric   assert((Rem->getOpcode() == Instruction::SRem ||
3783861d79fSDimitry Andric           Rem->getOpcode() == Instruction::URem) &&
3793861d79fSDimitry Andric          "Trying to expand remainder from a non-remainder function");
3803861d79fSDimitry Andric 
3813861d79fSDimitry Andric   IRBuilder<> Builder(Rem);
3823861d79fSDimitry Andric 
3837d523365SDimitry Andric   assert(!Rem->getType()->isVectorTy() && "Div over vectors not supported");
3847d523365SDimitry Andric   assert((Rem->getType()->getIntegerBitWidth() == 32 ||
3857d523365SDimitry Andric           Rem->getType()->getIntegerBitWidth() == 64) &&
3867d523365SDimitry Andric          "Div of bitwidth other than 32 or 64 not supported");
38791bc56edSDimitry Andric 
3883861d79fSDimitry Andric   // First prepare the sign if it's a signed remainder
3893861d79fSDimitry Andric   if (Rem->getOpcode() == Instruction::SRem) {
3903861d79fSDimitry Andric     Value *Remainder = generateSignedRemainderCode(Rem->getOperand(0),
3913861d79fSDimitry Andric                                                    Rem->getOperand(1), Builder);
3923861d79fSDimitry Andric 
3933ca95b02SDimitry Andric     // Check whether this is the insert point while Rem is still valid.
3943ca95b02SDimitry Andric     bool IsInsertPoint = Rem->getIterator() == Builder.GetInsertPoint();
3953861d79fSDimitry Andric     Rem->replaceAllUsesWith(Remainder);
3963861d79fSDimitry Andric     Rem->dropAllReferences();
3973861d79fSDimitry Andric     Rem->eraseFromParent();
3983861d79fSDimitry Andric 
39939d628a0SDimitry Andric     // If we didn't actually generate an urem instruction, we're done
40039d628a0SDimitry Andric     // This happens for example if the input were constant. In this case the
40139d628a0SDimitry Andric     // Builder insertion point was unchanged
4023ca95b02SDimitry Andric     if (IsInsertPoint)
4033861d79fSDimitry Andric       return true;
4043861d79fSDimitry Andric 
40539d628a0SDimitry Andric     BinaryOperator *BO = dyn_cast<BinaryOperator>(Builder.GetInsertPoint());
4063861d79fSDimitry Andric     Rem = BO;
4073861d79fSDimitry Andric   }
4083861d79fSDimitry Andric 
4093861d79fSDimitry Andric   Value *Remainder = generatedUnsignedRemainderCode(Rem->getOperand(0),
4103861d79fSDimitry Andric                                                     Rem->getOperand(1),
4113861d79fSDimitry Andric                                                     Builder);
4123861d79fSDimitry Andric 
4133861d79fSDimitry Andric   Rem->replaceAllUsesWith(Remainder);
4143861d79fSDimitry Andric   Rem->dropAllReferences();
4153861d79fSDimitry Andric   Rem->eraseFromParent();
4163861d79fSDimitry Andric 
4173861d79fSDimitry Andric   // Expand the udiv
4183861d79fSDimitry Andric   if (BinaryOperator *UDiv = dyn_cast<BinaryOperator>(Builder.GetInsertPoint())) {
4193861d79fSDimitry Andric     assert(UDiv->getOpcode() == Instruction::UDiv && "Non-udiv in expansion?");
4203861d79fSDimitry Andric     expandDivision(UDiv);
4213861d79fSDimitry Andric   }
4223861d79fSDimitry Andric 
4233861d79fSDimitry Andric   return true;
4243861d79fSDimitry Andric }
4253861d79fSDimitry Andric 
4263861d79fSDimitry Andric 
4273861d79fSDimitry Andric /// Generate code to divide two integers, replacing Div with the generated
4283861d79fSDimitry Andric /// code. This currently generates code similarly to compiler-rt's
4293861d79fSDimitry Andric /// implementations, but future work includes generating more specialized code
43091bc56edSDimitry Andric /// when more information about the operands are known. Implements both
43191bc56edSDimitry Andric /// 32bit and 64bit scalar division.
4323861d79fSDimitry Andric ///
433*4ba319b5SDimitry Andric /// Replace Div with generated code.
expandDivision(BinaryOperator * Div)4343861d79fSDimitry Andric bool llvm::expandDivision(BinaryOperator *Div) {
4353861d79fSDimitry Andric   assert((Div->getOpcode() == Instruction::SDiv ||
4363861d79fSDimitry Andric           Div->getOpcode() == Instruction::UDiv) &&
4373861d79fSDimitry Andric          "Trying to expand division from a non-division function");
4383861d79fSDimitry Andric 
4393861d79fSDimitry Andric   IRBuilder<> Builder(Div);
4403861d79fSDimitry Andric 
4417d523365SDimitry Andric   assert(!Div->getType()->isVectorTy() && "Div over vectors not supported");
4427d523365SDimitry Andric   assert((Div->getType()->getIntegerBitWidth() == 32 ||
4437d523365SDimitry Andric           Div->getType()->getIntegerBitWidth() == 64) &&
4447d523365SDimitry Andric          "Div of bitwidth other than 32 or 64 not supported");
44591bc56edSDimitry Andric 
4463861d79fSDimitry Andric   // First prepare the sign if it's a signed division
4473861d79fSDimitry Andric   if (Div->getOpcode() == Instruction::SDiv) {
4483861d79fSDimitry Andric     // Lower the code to unsigned division, and reset Div to point to the udiv.
4493861d79fSDimitry Andric     Value *Quotient = generateSignedDivisionCode(Div->getOperand(0),
4503861d79fSDimitry Andric                                                  Div->getOperand(1), Builder);
4513ca95b02SDimitry Andric 
4523ca95b02SDimitry Andric     // Check whether this is the insert point while Div is still valid.
4533ca95b02SDimitry Andric     bool IsInsertPoint = Div->getIterator() == Builder.GetInsertPoint();
4543861d79fSDimitry Andric     Div->replaceAllUsesWith(Quotient);
4553861d79fSDimitry Andric     Div->dropAllReferences();
4563861d79fSDimitry Andric     Div->eraseFromParent();
4573861d79fSDimitry Andric 
45839d628a0SDimitry Andric     // If we didn't actually generate an udiv instruction, we're done
45939d628a0SDimitry Andric     // This happens for example if the input were constant. In this case the
46039d628a0SDimitry Andric     // Builder insertion point was unchanged
4613ca95b02SDimitry Andric     if (IsInsertPoint)
4623861d79fSDimitry Andric       return true;
4633861d79fSDimitry Andric 
46439d628a0SDimitry Andric     BinaryOperator *BO = dyn_cast<BinaryOperator>(Builder.GetInsertPoint());
4653861d79fSDimitry Andric     Div = BO;
4663861d79fSDimitry Andric   }
4673861d79fSDimitry Andric 
4683861d79fSDimitry Andric   // Insert the unsigned division code
4693861d79fSDimitry Andric   Value *Quotient = generateUnsignedDivisionCode(Div->getOperand(0),
4703861d79fSDimitry Andric                                                  Div->getOperand(1),
4713861d79fSDimitry Andric                                                  Builder);
4723861d79fSDimitry Andric   Div->replaceAllUsesWith(Quotient);
4733861d79fSDimitry Andric   Div->dropAllReferences();
4743861d79fSDimitry Andric   Div->eraseFromParent();
4753861d79fSDimitry Andric 
4763861d79fSDimitry Andric   return true;
4773861d79fSDimitry Andric }
478139f7f9bSDimitry Andric 
479139f7f9bSDimitry Andric /// Generate code to compute the remainder of two integers of bitwidth up to
480139f7f9bSDimitry Andric /// 32 bits. Uses the above routines and extends the inputs/truncates the
481139f7f9bSDimitry Andric /// outputs to operate in 32 bits; that is, these routines are good for targets
482139f7f9bSDimitry Andric /// that have no or very little suppport for smaller than 32 bit integer
483139f7f9bSDimitry Andric /// arithmetic.
484139f7f9bSDimitry Andric ///
485*4ba319b5SDimitry Andric /// Replace Rem with emulation code.
expandRemainderUpTo32Bits(BinaryOperator * Rem)486139f7f9bSDimitry Andric bool llvm::expandRemainderUpTo32Bits(BinaryOperator *Rem) {
487139f7f9bSDimitry Andric   assert((Rem->getOpcode() == Instruction::SRem ||
488139f7f9bSDimitry Andric           Rem->getOpcode() == Instruction::URem) &&
489139f7f9bSDimitry Andric           "Trying to expand remainder from a non-remainder function");
490139f7f9bSDimitry Andric 
491139f7f9bSDimitry Andric   Type *RemTy = Rem->getType();
4927d523365SDimitry Andric   assert(!RemTy->isVectorTy() && "Div over vectors not supported");
493139f7f9bSDimitry Andric 
494139f7f9bSDimitry Andric   unsigned RemTyBitWidth = RemTy->getIntegerBitWidth();
495139f7f9bSDimitry Andric 
4967d523365SDimitry Andric   assert(RemTyBitWidth <= 32 &&
4977d523365SDimitry Andric          "Div of bitwidth greater than 32 not supported");
498139f7f9bSDimitry Andric 
499139f7f9bSDimitry Andric   if (RemTyBitWidth == 32)
500139f7f9bSDimitry Andric     return expandRemainder(Rem);
501139f7f9bSDimitry Andric 
50291bc56edSDimitry Andric   // If bitwidth smaller than 32 extend inputs, extend output and proceed
503139f7f9bSDimitry Andric   // with 32 bit division.
504139f7f9bSDimitry Andric   IRBuilder<> Builder(Rem);
505139f7f9bSDimitry Andric 
506139f7f9bSDimitry Andric   Value *ExtDividend;
507139f7f9bSDimitry Andric   Value *ExtDivisor;
508139f7f9bSDimitry Andric   Value *ExtRem;
509139f7f9bSDimitry Andric   Value *Trunc;
510139f7f9bSDimitry Andric   Type *Int32Ty = Builder.getInt32Ty();
511139f7f9bSDimitry Andric 
512139f7f9bSDimitry Andric   if (Rem->getOpcode() == Instruction::SRem) {
513139f7f9bSDimitry Andric     ExtDividend = Builder.CreateSExt(Rem->getOperand(0), Int32Ty);
514139f7f9bSDimitry Andric     ExtDivisor = Builder.CreateSExt(Rem->getOperand(1), Int32Ty);
515139f7f9bSDimitry Andric     ExtRem = Builder.CreateSRem(ExtDividend, ExtDivisor);
516139f7f9bSDimitry Andric   } else {
517139f7f9bSDimitry Andric     ExtDividend = Builder.CreateZExt(Rem->getOperand(0), Int32Ty);
518139f7f9bSDimitry Andric     ExtDivisor = Builder.CreateZExt(Rem->getOperand(1), Int32Ty);
519139f7f9bSDimitry Andric     ExtRem = Builder.CreateURem(ExtDividend, ExtDivisor);
520139f7f9bSDimitry Andric   }
521139f7f9bSDimitry Andric   Trunc = Builder.CreateTrunc(ExtRem, RemTy);
522139f7f9bSDimitry Andric 
523139f7f9bSDimitry Andric   Rem->replaceAllUsesWith(Trunc);
524139f7f9bSDimitry Andric   Rem->dropAllReferences();
525139f7f9bSDimitry Andric   Rem->eraseFromParent();
526139f7f9bSDimitry Andric 
527139f7f9bSDimitry Andric   return expandRemainder(cast<BinaryOperator>(ExtRem));
528139f7f9bSDimitry Andric }
529139f7f9bSDimitry Andric 
53091bc56edSDimitry Andric /// Generate code to compute the remainder of two integers of bitwidth up to
53191bc56edSDimitry Andric /// 64 bits. Uses the above routines and extends the inputs/truncates the
53291bc56edSDimitry Andric /// outputs to operate in 64 bits.
53391bc56edSDimitry Andric ///
534*4ba319b5SDimitry Andric /// Replace Rem with emulation code.
expandRemainderUpTo64Bits(BinaryOperator * Rem)53591bc56edSDimitry Andric bool llvm::expandRemainderUpTo64Bits(BinaryOperator *Rem) {
53691bc56edSDimitry Andric   assert((Rem->getOpcode() == Instruction::SRem ||
53791bc56edSDimitry Andric           Rem->getOpcode() == Instruction::URem) &&
53891bc56edSDimitry Andric           "Trying to expand remainder from a non-remainder function");
53991bc56edSDimitry Andric 
54091bc56edSDimitry Andric   Type *RemTy = Rem->getType();
5417d523365SDimitry Andric   assert(!RemTy->isVectorTy() && "Div over vectors not supported");
54291bc56edSDimitry Andric 
54391bc56edSDimitry Andric   unsigned RemTyBitWidth = RemTy->getIntegerBitWidth();
54491bc56edSDimitry Andric 
5457d523365SDimitry Andric   assert(RemTyBitWidth <= 64 && "Div of bitwidth greater than 64 not supported");
54691bc56edSDimitry Andric 
54791bc56edSDimitry Andric   if (RemTyBitWidth == 64)
54891bc56edSDimitry Andric     return expandRemainder(Rem);
54991bc56edSDimitry Andric 
55091bc56edSDimitry Andric   // If bitwidth smaller than 64 extend inputs, extend output and proceed
55191bc56edSDimitry Andric   // with 64 bit division.
55291bc56edSDimitry Andric   IRBuilder<> Builder(Rem);
55391bc56edSDimitry Andric 
55491bc56edSDimitry Andric   Value *ExtDividend;
55591bc56edSDimitry Andric   Value *ExtDivisor;
55691bc56edSDimitry Andric   Value *ExtRem;
55791bc56edSDimitry Andric   Value *Trunc;
55891bc56edSDimitry Andric   Type *Int64Ty = Builder.getInt64Ty();
55991bc56edSDimitry Andric 
56091bc56edSDimitry Andric   if (Rem->getOpcode() == Instruction::SRem) {
56191bc56edSDimitry Andric     ExtDividend = Builder.CreateSExt(Rem->getOperand(0), Int64Ty);
56291bc56edSDimitry Andric     ExtDivisor = Builder.CreateSExt(Rem->getOperand(1), Int64Ty);
56391bc56edSDimitry Andric     ExtRem = Builder.CreateSRem(ExtDividend, ExtDivisor);
56491bc56edSDimitry Andric   } else {
56591bc56edSDimitry Andric     ExtDividend = Builder.CreateZExt(Rem->getOperand(0), Int64Ty);
56691bc56edSDimitry Andric     ExtDivisor = Builder.CreateZExt(Rem->getOperand(1), Int64Ty);
56791bc56edSDimitry Andric     ExtRem = Builder.CreateURem(ExtDividend, ExtDivisor);
56891bc56edSDimitry Andric   }
56991bc56edSDimitry Andric   Trunc = Builder.CreateTrunc(ExtRem, RemTy);
57091bc56edSDimitry Andric 
57191bc56edSDimitry Andric   Rem->replaceAllUsesWith(Trunc);
57291bc56edSDimitry Andric   Rem->dropAllReferences();
57391bc56edSDimitry Andric   Rem->eraseFromParent();
57491bc56edSDimitry Andric 
57591bc56edSDimitry Andric   return expandRemainder(cast<BinaryOperator>(ExtRem));
57691bc56edSDimitry Andric }
577139f7f9bSDimitry Andric 
578139f7f9bSDimitry Andric /// Generate code to divide two integers of bitwidth up to 32 bits. Uses the
579139f7f9bSDimitry Andric /// above routines and extends the inputs/truncates the outputs to operate
580139f7f9bSDimitry Andric /// in 32 bits; that is, these routines are good for targets that have no
581139f7f9bSDimitry Andric /// or very little support for smaller than 32 bit integer arithmetic.
582139f7f9bSDimitry Andric ///
583*4ba319b5SDimitry Andric /// Replace Div with emulation code.
expandDivisionUpTo32Bits(BinaryOperator * Div)584139f7f9bSDimitry Andric bool llvm::expandDivisionUpTo32Bits(BinaryOperator *Div) {
585139f7f9bSDimitry Andric   assert((Div->getOpcode() == Instruction::SDiv ||
586139f7f9bSDimitry Andric           Div->getOpcode() == Instruction::UDiv) &&
587139f7f9bSDimitry Andric           "Trying to expand division from a non-division function");
588139f7f9bSDimitry Andric 
589139f7f9bSDimitry Andric   Type *DivTy = Div->getType();
5907d523365SDimitry Andric   assert(!DivTy->isVectorTy() && "Div over vectors not supported");
591139f7f9bSDimitry Andric 
592139f7f9bSDimitry Andric   unsigned DivTyBitWidth = DivTy->getIntegerBitWidth();
593139f7f9bSDimitry Andric 
5947d523365SDimitry Andric   assert(DivTyBitWidth <= 32 && "Div of bitwidth greater than 32 not supported");
595139f7f9bSDimitry Andric 
596139f7f9bSDimitry Andric   if (DivTyBitWidth == 32)
597139f7f9bSDimitry Andric     return expandDivision(Div);
598139f7f9bSDimitry Andric 
59991bc56edSDimitry Andric   // If bitwidth smaller than 32 extend inputs, extend output and proceed
600139f7f9bSDimitry Andric   // with 32 bit division.
601139f7f9bSDimitry Andric   IRBuilder<> Builder(Div);
602139f7f9bSDimitry Andric 
603139f7f9bSDimitry Andric   Value *ExtDividend;
604139f7f9bSDimitry Andric   Value *ExtDivisor;
605139f7f9bSDimitry Andric   Value *ExtDiv;
606139f7f9bSDimitry Andric   Value *Trunc;
607139f7f9bSDimitry Andric   Type *Int32Ty = Builder.getInt32Ty();
608139f7f9bSDimitry Andric 
609139f7f9bSDimitry Andric   if (Div->getOpcode() == Instruction::SDiv) {
610139f7f9bSDimitry Andric     ExtDividend = Builder.CreateSExt(Div->getOperand(0), Int32Ty);
611139f7f9bSDimitry Andric     ExtDivisor = Builder.CreateSExt(Div->getOperand(1), Int32Ty);
612139f7f9bSDimitry Andric     ExtDiv = Builder.CreateSDiv(ExtDividend, ExtDivisor);
613139f7f9bSDimitry Andric   } else {
614139f7f9bSDimitry Andric     ExtDividend = Builder.CreateZExt(Div->getOperand(0), Int32Ty);
615139f7f9bSDimitry Andric     ExtDivisor = Builder.CreateZExt(Div->getOperand(1), Int32Ty);
616139f7f9bSDimitry Andric     ExtDiv = Builder.CreateUDiv(ExtDividend, ExtDivisor);
617139f7f9bSDimitry Andric   }
618139f7f9bSDimitry Andric   Trunc = Builder.CreateTrunc(ExtDiv, DivTy);
619139f7f9bSDimitry Andric 
620139f7f9bSDimitry Andric   Div->replaceAllUsesWith(Trunc);
621139f7f9bSDimitry Andric   Div->dropAllReferences();
622139f7f9bSDimitry Andric   Div->eraseFromParent();
623139f7f9bSDimitry Andric 
624139f7f9bSDimitry Andric   return expandDivision(cast<BinaryOperator>(ExtDiv));
625139f7f9bSDimitry Andric }
62691bc56edSDimitry Andric 
62791bc56edSDimitry Andric /// Generate code to divide two integers of bitwidth up to 64 bits. Uses the
62891bc56edSDimitry Andric /// above routines and extends the inputs/truncates the outputs to operate
62991bc56edSDimitry Andric /// in 64 bits.
63091bc56edSDimitry Andric ///
631*4ba319b5SDimitry Andric /// Replace Div with emulation code.
expandDivisionUpTo64Bits(BinaryOperator * Div)63291bc56edSDimitry Andric bool llvm::expandDivisionUpTo64Bits(BinaryOperator *Div) {
63391bc56edSDimitry Andric   assert((Div->getOpcode() == Instruction::SDiv ||
63491bc56edSDimitry Andric           Div->getOpcode() == Instruction::UDiv) &&
63591bc56edSDimitry Andric           "Trying to expand division from a non-division function");
63691bc56edSDimitry Andric 
63791bc56edSDimitry Andric   Type *DivTy = Div->getType();
6387d523365SDimitry Andric   assert(!DivTy->isVectorTy() && "Div over vectors not supported");
63991bc56edSDimitry Andric 
64091bc56edSDimitry Andric   unsigned DivTyBitWidth = DivTy->getIntegerBitWidth();
64191bc56edSDimitry Andric 
6427d523365SDimitry Andric   assert(DivTyBitWidth <= 64 &&
6437d523365SDimitry Andric          "Div of bitwidth greater than 64 not supported");
64491bc56edSDimitry Andric 
64591bc56edSDimitry Andric   if (DivTyBitWidth == 64)
64691bc56edSDimitry Andric     return expandDivision(Div);
64791bc56edSDimitry Andric 
64891bc56edSDimitry Andric   // If bitwidth smaller than 64 extend inputs, extend output and proceed
64991bc56edSDimitry Andric   // with 64 bit division.
65091bc56edSDimitry Andric   IRBuilder<> Builder(Div);
65191bc56edSDimitry Andric 
65291bc56edSDimitry Andric   Value *ExtDividend;
65391bc56edSDimitry Andric   Value *ExtDivisor;
65491bc56edSDimitry Andric   Value *ExtDiv;
65591bc56edSDimitry Andric   Value *Trunc;
65691bc56edSDimitry Andric   Type *Int64Ty = Builder.getInt64Ty();
65791bc56edSDimitry Andric 
65891bc56edSDimitry Andric   if (Div->getOpcode() == Instruction::SDiv) {
65991bc56edSDimitry Andric     ExtDividend = Builder.CreateSExt(Div->getOperand(0), Int64Ty);
66091bc56edSDimitry Andric     ExtDivisor = Builder.CreateSExt(Div->getOperand(1), Int64Ty);
66191bc56edSDimitry Andric     ExtDiv = Builder.CreateSDiv(ExtDividend, ExtDivisor);
66291bc56edSDimitry Andric   } else {
66391bc56edSDimitry Andric     ExtDividend = Builder.CreateZExt(Div->getOperand(0), Int64Ty);
66491bc56edSDimitry Andric     ExtDivisor = Builder.CreateZExt(Div->getOperand(1), Int64Ty);
66591bc56edSDimitry Andric     ExtDiv = Builder.CreateUDiv(ExtDividend, ExtDivisor);
66691bc56edSDimitry Andric   }
66791bc56edSDimitry Andric   Trunc = Builder.CreateTrunc(ExtDiv, DivTy);
66891bc56edSDimitry Andric 
66991bc56edSDimitry Andric   Div->replaceAllUsesWith(Trunc);
67091bc56edSDimitry Andric   Div->dropAllReferences();
67191bc56edSDimitry Andric   Div->eraseFromParent();
67291bc56edSDimitry Andric 
67391bc56edSDimitry Andric   return expandDivision(cast<BinaryOperator>(ExtDiv));
67491bc56edSDimitry Andric }
675