xref: /aosp_15_r20/external/llvm/lib/Transforms/Utils/BypassSlowDivision.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
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