1*9880d681SAndroid Build Coastguard Worker //===-- BypassSlowDivision.cpp - Bypass slow division ---------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file contains an optimization for div and rem on architectures that
11*9880d681SAndroid Build Coastguard Worker // execute short instructions significantly faster than longer instructions.
12*9880d681SAndroid Build Coastguard Worker // For example, on Intel Atom 32-bit divides are slow enough that during
13*9880d681SAndroid Build Coastguard Worker // runtime it is profitable to check the value of the operands, and if they are
14*9880d681SAndroid Build Coastguard Worker // positive and less than 256 use an unsigned 8-bit divide.
15*9880d681SAndroid Build Coastguard Worker //
16*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
17*9880d681SAndroid Build Coastguard Worker
18*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Utils/BypassSlowDivision.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/DenseMap.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Function.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/IRBuilder.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Instructions.h"
23*9880d681SAndroid Build Coastguard Worker
24*9880d681SAndroid Build Coastguard Worker using namespace llvm;
25*9880d681SAndroid Build Coastguard Worker
26*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "bypass-slow-division"
27*9880d681SAndroid Build Coastguard Worker
28*9880d681SAndroid Build Coastguard Worker namespace {
29*9880d681SAndroid Build Coastguard Worker struct DivOpInfo {
30*9880d681SAndroid Build Coastguard Worker bool SignedOp;
31*9880d681SAndroid Build Coastguard Worker Value *Dividend;
32*9880d681SAndroid Build Coastguard Worker Value *Divisor;
33*9880d681SAndroid Build Coastguard Worker
DivOpInfo__anon70da5a820111::DivOpInfo34*9880d681SAndroid Build Coastguard Worker DivOpInfo(bool InSignedOp, Value *InDividend, Value *InDivisor)
35*9880d681SAndroid Build Coastguard Worker : SignedOp(InSignedOp), Dividend(InDividend), Divisor(InDivisor) {}
36*9880d681SAndroid Build Coastguard Worker };
37*9880d681SAndroid Build Coastguard Worker
38*9880d681SAndroid Build Coastguard Worker struct DivPhiNodes {
39*9880d681SAndroid Build Coastguard Worker PHINode *Quotient;
40*9880d681SAndroid Build Coastguard Worker PHINode *Remainder;
41*9880d681SAndroid Build Coastguard Worker
DivPhiNodes__anon70da5a820111::DivPhiNodes42*9880d681SAndroid Build Coastguard Worker DivPhiNodes(PHINode *InQuotient, PHINode *InRemainder)
43*9880d681SAndroid Build Coastguard Worker : Quotient(InQuotient), Remainder(InRemainder) {}
44*9880d681SAndroid Build Coastguard Worker };
45*9880d681SAndroid Build Coastguard Worker }
46*9880d681SAndroid Build Coastguard Worker
47*9880d681SAndroid Build Coastguard Worker namespace llvm {
48*9880d681SAndroid Build Coastguard Worker template<>
49*9880d681SAndroid Build Coastguard Worker struct DenseMapInfo<DivOpInfo> {
isEqualllvm::DenseMapInfo50*9880d681SAndroid Build Coastguard Worker static bool isEqual(const DivOpInfo &Val1, const DivOpInfo &Val2) {
51*9880d681SAndroid Build Coastguard Worker return Val1.SignedOp == Val2.SignedOp &&
52*9880d681SAndroid Build Coastguard Worker Val1.Dividend == Val2.Dividend &&
53*9880d681SAndroid Build Coastguard Worker Val1.Divisor == Val2.Divisor;
54*9880d681SAndroid Build Coastguard Worker }
55*9880d681SAndroid Build Coastguard Worker
getEmptyKeyllvm::DenseMapInfo56*9880d681SAndroid Build Coastguard Worker static DivOpInfo getEmptyKey() {
57*9880d681SAndroid Build Coastguard Worker return DivOpInfo(false, nullptr, nullptr);
58*9880d681SAndroid Build Coastguard Worker }
59*9880d681SAndroid Build Coastguard Worker
getTombstoneKeyllvm::DenseMapInfo60*9880d681SAndroid Build Coastguard Worker static DivOpInfo getTombstoneKey() {
61*9880d681SAndroid Build Coastguard Worker return DivOpInfo(true, nullptr, nullptr);
62*9880d681SAndroid Build Coastguard Worker }
63*9880d681SAndroid Build Coastguard Worker
getHashValuellvm::DenseMapInfo64*9880d681SAndroid Build Coastguard Worker static unsigned getHashValue(const DivOpInfo &Val) {
65*9880d681SAndroid Build Coastguard Worker return (unsigned)(reinterpret_cast<uintptr_t>(Val.Dividend) ^
66*9880d681SAndroid Build Coastguard Worker reinterpret_cast<uintptr_t>(Val.Divisor)) ^
67*9880d681SAndroid Build Coastguard Worker (unsigned)Val.SignedOp;
68*9880d681SAndroid Build Coastguard Worker }
69*9880d681SAndroid Build Coastguard Worker };
70*9880d681SAndroid Build Coastguard Worker
71*9880d681SAndroid Build Coastguard Worker typedef DenseMap<DivOpInfo, DivPhiNodes> DivCacheTy;
72*9880d681SAndroid Build Coastguard Worker }
73*9880d681SAndroid Build Coastguard Worker
74*9880d681SAndroid Build Coastguard Worker // insertFastDiv - Substitutes the div/rem instruction with code that checks the
75*9880d681SAndroid Build Coastguard Worker // value of the operands and uses a shorter-faster div/rem instruction when
76*9880d681SAndroid Build Coastguard Worker // possible and the longer-slower div/rem instruction otherwise.
insertFastDiv(Instruction * I,IntegerType * BypassType,bool UseDivOp,bool UseSignedOp,DivCacheTy & PerBBDivCache)77*9880d681SAndroid Build Coastguard Worker static bool insertFastDiv(Instruction *I, IntegerType *BypassType,
78*9880d681SAndroid Build Coastguard Worker bool UseDivOp, bool UseSignedOp,
79*9880d681SAndroid Build Coastguard Worker DivCacheTy &PerBBDivCache) {
80*9880d681SAndroid Build Coastguard Worker Function *F = I->getParent()->getParent();
81*9880d681SAndroid Build Coastguard Worker // Get instruction operands
82*9880d681SAndroid Build Coastguard Worker Value *Dividend = I->getOperand(0);
83*9880d681SAndroid Build Coastguard Worker Value *Divisor = I->getOperand(1);
84*9880d681SAndroid Build Coastguard Worker
85*9880d681SAndroid Build Coastguard Worker if (isa<ConstantInt>(Divisor) ||
86*9880d681SAndroid Build Coastguard Worker (isa<ConstantInt>(Dividend) && isa<ConstantInt>(Divisor))) {
87*9880d681SAndroid Build Coastguard Worker // Operations with immediate values should have
88*9880d681SAndroid Build Coastguard Worker // been solved and replaced during compile time.
89*9880d681SAndroid Build Coastguard Worker return false;
90*9880d681SAndroid Build Coastguard Worker }
91*9880d681SAndroid Build Coastguard Worker
92*9880d681SAndroid Build Coastguard Worker // Basic Block is split before divide
93*9880d681SAndroid Build Coastguard Worker BasicBlock *MainBB = &*I->getParent();
94*9880d681SAndroid Build Coastguard Worker BasicBlock *SuccessorBB = MainBB->splitBasicBlock(I);
95*9880d681SAndroid Build Coastguard Worker
96*9880d681SAndroid Build Coastguard Worker // Add new basic block for slow divide operation
97*9880d681SAndroid Build Coastguard Worker BasicBlock *SlowBB =
98*9880d681SAndroid Build Coastguard Worker BasicBlock::Create(F->getContext(), "", MainBB->getParent(), SuccessorBB);
99*9880d681SAndroid Build Coastguard Worker SlowBB->moveBefore(SuccessorBB);
100*9880d681SAndroid Build Coastguard Worker IRBuilder<> SlowBuilder(SlowBB, SlowBB->begin());
101*9880d681SAndroid Build Coastguard Worker Value *SlowQuotientV;
102*9880d681SAndroid Build Coastguard Worker Value *SlowRemainderV;
103*9880d681SAndroid Build Coastguard Worker if (UseSignedOp) {
104*9880d681SAndroid Build Coastguard Worker SlowQuotientV = SlowBuilder.CreateSDiv(Dividend, Divisor);
105*9880d681SAndroid Build Coastguard Worker SlowRemainderV = SlowBuilder.CreateSRem(Dividend, Divisor);
106*9880d681SAndroid Build Coastguard Worker } else {
107*9880d681SAndroid Build Coastguard Worker SlowQuotientV = SlowBuilder.CreateUDiv(Dividend, Divisor);
108*9880d681SAndroid Build Coastguard Worker SlowRemainderV = SlowBuilder.CreateURem(Dividend, Divisor);
109*9880d681SAndroid Build Coastguard Worker }
110*9880d681SAndroid Build Coastguard Worker SlowBuilder.CreateBr(SuccessorBB);
111*9880d681SAndroid Build Coastguard Worker
112*9880d681SAndroid Build Coastguard Worker // Add new basic block for fast divide operation
113*9880d681SAndroid Build Coastguard Worker BasicBlock *FastBB =
114*9880d681SAndroid Build Coastguard Worker BasicBlock::Create(F->getContext(), "", MainBB->getParent(), SuccessorBB);
115*9880d681SAndroid Build Coastguard Worker FastBB->moveBefore(SlowBB);
116*9880d681SAndroid Build Coastguard Worker IRBuilder<> FastBuilder(FastBB, FastBB->begin());
117*9880d681SAndroid Build Coastguard Worker Value *ShortDivisorV = FastBuilder.CreateCast(Instruction::Trunc, Divisor,
118*9880d681SAndroid Build Coastguard Worker BypassType);
119*9880d681SAndroid Build Coastguard Worker Value *ShortDividendV = FastBuilder.CreateCast(Instruction::Trunc, Dividend,
120*9880d681SAndroid Build Coastguard Worker BypassType);
121*9880d681SAndroid Build Coastguard Worker
122*9880d681SAndroid Build Coastguard Worker // udiv/urem because optimization only handles positive numbers
123*9880d681SAndroid Build Coastguard Worker Value *ShortQuotientV = FastBuilder.CreateExactUDiv(ShortDividendV,
124*9880d681SAndroid Build Coastguard Worker ShortDivisorV);
125*9880d681SAndroid Build Coastguard Worker Value *ShortRemainderV = FastBuilder.CreateURem(ShortDividendV,
126*9880d681SAndroid Build Coastguard Worker ShortDivisorV);
127*9880d681SAndroid Build Coastguard Worker Value *FastQuotientV = FastBuilder.CreateCast(Instruction::ZExt,
128*9880d681SAndroid Build Coastguard Worker ShortQuotientV,
129*9880d681SAndroid Build Coastguard Worker Dividend->getType());
130*9880d681SAndroid Build Coastguard Worker Value *FastRemainderV = FastBuilder.CreateCast(Instruction::ZExt,
131*9880d681SAndroid Build Coastguard Worker ShortRemainderV,
132*9880d681SAndroid Build Coastguard Worker Dividend->getType());
133*9880d681SAndroid Build Coastguard Worker FastBuilder.CreateBr(SuccessorBB);
134*9880d681SAndroid Build Coastguard Worker
135*9880d681SAndroid Build Coastguard Worker // Phi nodes for result of div and rem
136*9880d681SAndroid Build Coastguard Worker IRBuilder<> SuccessorBuilder(SuccessorBB, SuccessorBB->begin());
137*9880d681SAndroid Build Coastguard Worker PHINode *QuoPhi = SuccessorBuilder.CreatePHI(I->getType(), 2);
138*9880d681SAndroid Build Coastguard Worker QuoPhi->addIncoming(SlowQuotientV, SlowBB);
139*9880d681SAndroid Build Coastguard Worker QuoPhi->addIncoming(FastQuotientV, FastBB);
140*9880d681SAndroid Build Coastguard Worker PHINode *RemPhi = SuccessorBuilder.CreatePHI(I->getType(), 2);
141*9880d681SAndroid Build Coastguard Worker RemPhi->addIncoming(SlowRemainderV, SlowBB);
142*9880d681SAndroid Build Coastguard Worker RemPhi->addIncoming(FastRemainderV, FastBB);
143*9880d681SAndroid Build Coastguard Worker
144*9880d681SAndroid Build Coastguard Worker // Replace I with appropriate phi node
145*9880d681SAndroid Build Coastguard Worker if (UseDivOp)
146*9880d681SAndroid Build Coastguard Worker I->replaceAllUsesWith(QuoPhi);
147*9880d681SAndroid Build Coastguard Worker else
148*9880d681SAndroid Build Coastguard Worker I->replaceAllUsesWith(RemPhi);
149*9880d681SAndroid Build Coastguard Worker I->eraseFromParent();
150*9880d681SAndroid Build Coastguard Worker
151*9880d681SAndroid Build Coastguard Worker // Combine operands into a single value with OR for value testing below
152*9880d681SAndroid Build Coastguard Worker MainBB->getInstList().back().eraseFromParent();
153*9880d681SAndroid Build Coastguard Worker IRBuilder<> MainBuilder(MainBB, MainBB->end());
154*9880d681SAndroid Build Coastguard Worker Value *OrV = MainBuilder.CreateOr(Dividend, Divisor);
155*9880d681SAndroid Build Coastguard Worker
156*9880d681SAndroid Build Coastguard Worker // BitMask is inverted to check if the operands are
157*9880d681SAndroid Build Coastguard Worker // larger than the bypass type
158*9880d681SAndroid Build Coastguard Worker uint64_t BitMask = ~BypassType->getBitMask();
159*9880d681SAndroid Build Coastguard Worker Value *AndV = MainBuilder.CreateAnd(OrV, BitMask);
160*9880d681SAndroid Build Coastguard Worker
161*9880d681SAndroid Build Coastguard Worker // Compare operand values and branch
162*9880d681SAndroid Build Coastguard Worker Value *ZeroV = ConstantInt::getSigned(Dividend->getType(), 0);
163*9880d681SAndroid Build Coastguard Worker Value *CmpV = MainBuilder.CreateICmpEQ(AndV, ZeroV);
164*9880d681SAndroid Build Coastguard Worker MainBuilder.CreateCondBr(CmpV, FastBB, SlowBB);
165*9880d681SAndroid Build Coastguard Worker
166*9880d681SAndroid Build Coastguard Worker // Cache phi nodes to be used later in place of other instances
167*9880d681SAndroid Build Coastguard Worker // of div or rem with the same sign, dividend, and divisor
168*9880d681SAndroid Build Coastguard Worker DivOpInfo Key(UseSignedOp, Dividend, Divisor);
169*9880d681SAndroid Build Coastguard Worker DivPhiNodes Value(QuoPhi, RemPhi);
170*9880d681SAndroid Build Coastguard Worker PerBBDivCache.insert(std::pair<DivOpInfo, DivPhiNodes>(Key, Value));
171*9880d681SAndroid Build Coastguard Worker return true;
172*9880d681SAndroid Build Coastguard Worker }
173*9880d681SAndroid Build Coastguard Worker
174*9880d681SAndroid Build Coastguard Worker // reuseOrInsertFastDiv - Reuses previously computed dividend or remainder from
175*9880d681SAndroid Build Coastguard Worker // the current BB if operands and operation are identical. Otherwise calls
176*9880d681SAndroid Build Coastguard Worker // insertFastDiv to perform the optimization and caches the resulting dividend
177*9880d681SAndroid Build Coastguard Worker // and remainder.
reuseOrInsertFastDiv(Instruction * I,IntegerType * BypassType,bool UseDivOp,bool UseSignedOp,DivCacheTy & PerBBDivCache)178*9880d681SAndroid Build Coastguard Worker static bool reuseOrInsertFastDiv(Instruction *I, IntegerType *BypassType,
179*9880d681SAndroid Build Coastguard Worker bool UseDivOp, bool UseSignedOp,
180*9880d681SAndroid Build Coastguard Worker DivCacheTy &PerBBDivCache) {
181*9880d681SAndroid Build Coastguard Worker // Get instruction operands
182*9880d681SAndroid Build Coastguard Worker DivOpInfo Key(UseSignedOp, I->getOperand(0), I->getOperand(1));
183*9880d681SAndroid Build Coastguard Worker DivCacheTy::iterator CacheI = PerBBDivCache.find(Key);
184*9880d681SAndroid Build Coastguard Worker
185*9880d681SAndroid Build Coastguard Worker if (CacheI == PerBBDivCache.end()) {
186*9880d681SAndroid Build Coastguard Worker // If previous instance does not exist, insert fast div
187*9880d681SAndroid Build Coastguard Worker return insertFastDiv(I, BypassType, UseDivOp, UseSignedOp, PerBBDivCache);
188*9880d681SAndroid Build Coastguard Worker }
189*9880d681SAndroid Build Coastguard Worker
190*9880d681SAndroid Build Coastguard Worker // Replace operation value with previously generated phi node
191*9880d681SAndroid Build Coastguard Worker DivPhiNodes &Value = CacheI->second;
192*9880d681SAndroid Build Coastguard Worker if (UseDivOp) {
193*9880d681SAndroid Build Coastguard Worker // Replace all uses of div instruction with quotient phi node
194*9880d681SAndroid Build Coastguard Worker I->replaceAllUsesWith(Value.Quotient);
195*9880d681SAndroid Build Coastguard Worker } else {
196*9880d681SAndroid Build Coastguard Worker // Replace all uses of rem instruction with remainder phi node
197*9880d681SAndroid Build Coastguard Worker I->replaceAllUsesWith(Value.Remainder);
198*9880d681SAndroid Build Coastguard Worker }
199*9880d681SAndroid Build Coastguard Worker
200*9880d681SAndroid Build Coastguard Worker // Remove redundant operation
201*9880d681SAndroid Build Coastguard Worker I->eraseFromParent();
202*9880d681SAndroid Build Coastguard Worker return true;
203*9880d681SAndroid Build Coastguard Worker }
204*9880d681SAndroid Build Coastguard Worker
205*9880d681SAndroid Build Coastguard Worker // bypassSlowDivision - This optimization identifies DIV instructions in a BB
206*9880d681SAndroid Build Coastguard Worker // that can be profitably bypassed and carried out with a shorter, faster
207*9880d681SAndroid Build Coastguard Worker // divide.
bypassSlowDivision(BasicBlock * BB,const DenseMap<unsigned int,unsigned int> & BypassWidths)208*9880d681SAndroid Build Coastguard Worker bool llvm::bypassSlowDivision(
209*9880d681SAndroid Build Coastguard Worker BasicBlock *BB, const DenseMap<unsigned int, unsigned int> &BypassWidths) {
210*9880d681SAndroid Build Coastguard Worker DivCacheTy DivCache;
211*9880d681SAndroid Build Coastguard Worker
212*9880d681SAndroid Build Coastguard Worker bool MadeChange = false;
213*9880d681SAndroid Build Coastguard Worker Instruction* Next = &*BB->begin();
214*9880d681SAndroid Build Coastguard Worker while (Next != nullptr) {
215*9880d681SAndroid Build Coastguard Worker // We may add instructions immediately after I, but we want to skip over
216*9880d681SAndroid Build Coastguard Worker // them.
217*9880d681SAndroid Build Coastguard Worker Instruction* I = Next;
218*9880d681SAndroid Build Coastguard Worker Next = Next->getNextNode();
219*9880d681SAndroid Build Coastguard Worker
220*9880d681SAndroid Build Coastguard Worker // Get instruction details
221*9880d681SAndroid Build Coastguard Worker unsigned Opcode = I->getOpcode();
222*9880d681SAndroid Build Coastguard Worker bool UseDivOp = Opcode == Instruction::SDiv || Opcode == Instruction::UDiv;
223*9880d681SAndroid Build Coastguard Worker bool UseRemOp = Opcode == Instruction::SRem || Opcode == Instruction::URem;
224*9880d681SAndroid Build Coastguard Worker bool UseSignedOp = Opcode == Instruction::SDiv ||
225*9880d681SAndroid Build Coastguard Worker Opcode == Instruction::SRem;
226*9880d681SAndroid Build Coastguard Worker
227*9880d681SAndroid Build Coastguard Worker // Only optimize div or rem ops
228*9880d681SAndroid Build Coastguard Worker if (!UseDivOp && !UseRemOp)
229*9880d681SAndroid Build Coastguard Worker continue;
230*9880d681SAndroid Build Coastguard Worker
231*9880d681SAndroid Build Coastguard Worker // Skip division on vector types, only optimize integer instructions
232*9880d681SAndroid Build Coastguard Worker if (!I->getType()->isIntegerTy())
233*9880d681SAndroid Build Coastguard Worker continue;
234*9880d681SAndroid Build Coastguard Worker
235*9880d681SAndroid Build Coastguard Worker // Get bitwidth of div/rem instruction
236*9880d681SAndroid Build Coastguard Worker IntegerType *T = cast<IntegerType>(I->getType());
237*9880d681SAndroid Build Coastguard Worker unsigned int bitwidth = T->getBitWidth();
238*9880d681SAndroid Build Coastguard Worker
239*9880d681SAndroid Build Coastguard Worker // Continue if bitwidth is not bypassed
240*9880d681SAndroid Build Coastguard Worker DenseMap<unsigned int, unsigned int>::const_iterator BI = BypassWidths.find(bitwidth);
241*9880d681SAndroid Build Coastguard Worker if (BI == BypassWidths.end())
242*9880d681SAndroid Build Coastguard Worker continue;
243*9880d681SAndroid Build Coastguard Worker
244*9880d681SAndroid Build Coastguard Worker // Get type for div/rem instruction with bypass bitwidth
245*9880d681SAndroid Build Coastguard Worker IntegerType *BT = IntegerType::get(I->getContext(), BI->second);
246*9880d681SAndroid Build Coastguard Worker
247*9880d681SAndroid Build Coastguard Worker MadeChange |= reuseOrInsertFastDiv(I, BT, UseDivOp, UseSignedOp, DivCache);
248*9880d681SAndroid Build Coastguard Worker }
249*9880d681SAndroid Build Coastguard Worker
250*9880d681SAndroid Build Coastguard Worker return MadeChange;
251*9880d681SAndroid Build Coastguard Worker }
252