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