1*6fd4391dSSanjay Patel //===- DivRemPairs.cpp - Hoist/decompose division and remainder -*- C++ -*-===//
2*6fd4391dSSanjay Patel //
3*6fd4391dSSanjay Patel //                     The LLVM Compiler Infrastructure
4*6fd4391dSSanjay Patel //
5*6fd4391dSSanjay Patel // This file is distributed under the University of Illinois Open Source
6*6fd4391dSSanjay Patel // License. See LICENSE.TXT for details.
7*6fd4391dSSanjay Patel //
8*6fd4391dSSanjay Patel //===----------------------------------------------------------------------===//
9*6fd4391dSSanjay Patel //
10*6fd4391dSSanjay Patel // This pass hoists and/or decomposes integer division and remainder
11*6fd4391dSSanjay Patel // instructions to enable CFG improvements and better codegen.
12*6fd4391dSSanjay Patel //
13*6fd4391dSSanjay Patel //===----------------------------------------------------------------------===//
14*6fd4391dSSanjay Patel 
15*6fd4391dSSanjay Patel #include "llvm/Transforms/Scalar/DivRemPairs.h"
16*6fd4391dSSanjay Patel #include "llvm/ADT/Statistic.h"
17*6fd4391dSSanjay Patel #include "llvm/Analysis/GlobalsModRef.h"
18*6fd4391dSSanjay Patel #include "llvm/Analysis/TargetTransformInfo.h"
19*6fd4391dSSanjay Patel #include "llvm/IR/Dominators.h"
20*6fd4391dSSanjay Patel #include "llvm/IR/Function.h"
21*6fd4391dSSanjay Patel #include "llvm/Pass.h"
22*6fd4391dSSanjay Patel #include "llvm/Transforms/Scalar.h"
23*6fd4391dSSanjay Patel #include "llvm/Transforms/Utils/BypassSlowDivision.h"
24*6fd4391dSSanjay Patel using namespace llvm;
25*6fd4391dSSanjay Patel 
26*6fd4391dSSanjay Patel #define DEBUG_TYPE "div-rem-pairs"
27*6fd4391dSSanjay Patel STATISTIC(NumPairs, "Number of div/rem pairs");
28*6fd4391dSSanjay Patel STATISTIC(NumHoisted, "Number of instructions hoisted");
29*6fd4391dSSanjay Patel STATISTIC(NumDecomposed, "Number of instructions decomposed");
30*6fd4391dSSanjay Patel 
31*6fd4391dSSanjay Patel /// Find matching pairs of integer div/rem ops (they have the same numerator,
32*6fd4391dSSanjay Patel /// denominator, and signedness). If they exist in different basic blocks, bring
33*6fd4391dSSanjay Patel /// them together by hoisting or replace the common division operation that is
34*6fd4391dSSanjay Patel /// implicit in the remainder:
35*6fd4391dSSanjay Patel /// X % Y <--> X - ((X / Y) * Y).
36*6fd4391dSSanjay Patel ///
37*6fd4391dSSanjay Patel /// We can largely ignore the normal safety and cost constraints on speculation
38*6fd4391dSSanjay Patel /// of these ops when we find a matching pair. This is because we are already
39*6fd4391dSSanjay Patel /// guaranteed that any exceptions and most cost are already incurred by the
40*6fd4391dSSanjay Patel /// first member of the pair.
41*6fd4391dSSanjay Patel ///
42*6fd4391dSSanjay Patel /// Note: This transform could be an oddball enhancement to EarlyCSE, GVN, or
43*6fd4391dSSanjay Patel /// SimplifyCFG, but it's split off on its own because it's different enough
44*6fd4391dSSanjay Patel /// that it doesn't quite match the stated objectives of those passes.
45*6fd4391dSSanjay Patel static bool optimizeDivRem(Function &F, const TargetTransformInfo &TTI,
46*6fd4391dSSanjay Patel                            const DominatorTree &DT) {
47*6fd4391dSSanjay Patel   bool Changed = false;
48*6fd4391dSSanjay Patel 
49*6fd4391dSSanjay Patel   // Insert all divide and remainder instructions into maps keyed by their
50*6fd4391dSSanjay Patel   // operands and opcode (signed or unsigned).
51*6fd4391dSSanjay Patel   DenseMap<DivRemMapKey, Instruction *> DivMap, RemMap;
52*6fd4391dSSanjay Patel   for (auto &BB : F) {
53*6fd4391dSSanjay Patel     for (auto &I : BB) {
54*6fd4391dSSanjay Patel       if (I.getOpcode() == Instruction::SDiv)
55*6fd4391dSSanjay Patel         DivMap[DivRemMapKey(true, I.getOperand(0), I.getOperand(1))] = &I;
56*6fd4391dSSanjay Patel       else if (I.getOpcode() == Instruction::UDiv)
57*6fd4391dSSanjay Patel         DivMap[DivRemMapKey(false, I.getOperand(0), I.getOperand(1))] = &I;
58*6fd4391dSSanjay Patel       else if (I.getOpcode() == Instruction::SRem)
59*6fd4391dSSanjay Patel         RemMap[DivRemMapKey(true, I.getOperand(0), I.getOperand(1))] = &I;
60*6fd4391dSSanjay Patel       else if (I.getOpcode() == Instruction::URem)
61*6fd4391dSSanjay Patel         RemMap[DivRemMapKey(false, I.getOperand(0), I.getOperand(1))] = &I;
62*6fd4391dSSanjay Patel     }
63*6fd4391dSSanjay Patel   }
64*6fd4391dSSanjay Patel 
65*6fd4391dSSanjay Patel   // We can iterate over either map because we are only looking for matched
66*6fd4391dSSanjay Patel   // pairs. Choose remainders for efficiency because they are usually even more
67*6fd4391dSSanjay Patel   // rare than division.
68*6fd4391dSSanjay Patel   for (auto &RemPair : RemMap) {
69*6fd4391dSSanjay Patel     // Find the matching division instruction from the division map.
70*6fd4391dSSanjay Patel     Instruction *DivInst = DivMap[RemPair.getFirst()];
71*6fd4391dSSanjay Patel     if (!DivInst)
72*6fd4391dSSanjay Patel       continue;
73*6fd4391dSSanjay Patel 
74*6fd4391dSSanjay Patel     // We have a matching pair of div/rem instructions. If one dominates the
75*6fd4391dSSanjay Patel     // other, hoist and/or replace one.
76*6fd4391dSSanjay Patel     NumPairs++;
77*6fd4391dSSanjay Patel     Instruction *RemInst = RemPair.getSecond();
78*6fd4391dSSanjay Patel     bool IsSigned = DivInst->getOpcode() == Instruction::SDiv;
79*6fd4391dSSanjay Patel     bool HasDivRemOp = TTI.hasDivRemOp(DivInst->getType(), IsSigned);
80*6fd4391dSSanjay Patel 
81*6fd4391dSSanjay Patel     // If the target supports div+rem and the instructions are in the same block
82*6fd4391dSSanjay Patel     // already, there's nothing to do. The backend should handle this. If the
83*6fd4391dSSanjay Patel     // target does not support div+rem, then we will decompose the rem.
84*6fd4391dSSanjay Patel     if (HasDivRemOp && RemInst->getParent() == DivInst->getParent())
85*6fd4391dSSanjay Patel       continue;
86*6fd4391dSSanjay Patel 
87*6fd4391dSSanjay Patel     bool DivDominates = DT.dominates(DivInst, RemInst);
88*6fd4391dSSanjay Patel     if (!DivDominates && !DT.dominates(RemInst, DivInst))
89*6fd4391dSSanjay Patel       continue;
90*6fd4391dSSanjay Patel 
91*6fd4391dSSanjay Patel     if (HasDivRemOp) {
92*6fd4391dSSanjay Patel       // The target has a single div/rem operation. Hoist the lower instruction
93*6fd4391dSSanjay Patel       // to make the matched pair visible to the backend.
94*6fd4391dSSanjay Patel       if (DivDominates)
95*6fd4391dSSanjay Patel         RemInst->moveAfter(DivInst);
96*6fd4391dSSanjay Patel       else
97*6fd4391dSSanjay Patel         DivInst->moveAfter(RemInst);
98*6fd4391dSSanjay Patel       NumHoisted++;
99*6fd4391dSSanjay Patel     } else {
100*6fd4391dSSanjay Patel       // The target does not have a single div/rem operation. Decompose the
101*6fd4391dSSanjay Patel       // remainder calculation as:
102*6fd4391dSSanjay Patel       // X % Y --> X - ((X / Y) * Y).
103*6fd4391dSSanjay Patel       Value *X = RemInst->getOperand(0);
104*6fd4391dSSanjay Patel       Value *Y = RemInst->getOperand(1);
105*6fd4391dSSanjay Patel       Instruction *Mul = BinaryOperator::CreateMul(DivInst, Y);
106*6fd4391dSSanjay Patel       Instruction *Sub = BinaryOperator::CreateSub(X, Mul);
107*6fd4391dSSanjay Patel 
108*6fd4391dSSanjay Patel       // If the remainder dominates, then hoist the division up to that block:
109*6fd4391dSSanjay Patel       //
110*6fd4391dSSanjay Patel       // bb1:
111*6fd4391dSSanjay Patel       //   %rem = srem %x, %y
112*6fd4391dSSanjay Patel       // bb2:
113*6fd4391dSSanjay Patel       //   %div = sdiv %x, %y
114*6fd4391dSSanjay Patel       // -->
115*6fd4391dSSanjay Patel       // bb1:
116*6fd4391dSSanjay Patel       //   %div = sdiv %x, %y
117*6fd4391dSSanjay Patel       //   %mul = mul %div, %y
118*6fd4391dSSanjay Patel       //   %rem = sub %x, %mul
119*6fd4391dSSanjay Patel       //
120*6fd4391dSSanjay Patel       // If the division dominates, it's already in the right place. The mul+sub
121*6fd4391dSSanjay Patel       // will be in a different block because we don't assume that they are
122*6fd4391dSSanjay Patel       // cheap to speculatively execute:
123*6fd4391dSSanjay Patel       //
124*6fd4391dSSanjay Patel       // bb1:
125*6fd4391dSSanjay Patel       //   %div = sdiv %x, %y
126*6fd4391dSSanjay Patel       // bb2:
127*6fd4391dSSanjay Patel       //   %rem = srem %x, %y
128*6fd4391dSSanjay Patel       // -->
129*6fd4391dSSanjay Patel       // bb1:
130*6fd4391dSSanjay Patel       //   %div = sdiv %x, %y
131*6fd4391dSSanjay Patel       // bb2:
132*6fd4391dSSanjay Patel       //   %mul = mul %div, %y
133*6fd4391dSSanjay Patel       //   %rem = sub %x, %mul
134*6fd4391dSSanjay Patel       //
135*6fd4391dSSanjay Patel       // If the div and rem are in the same block, we do the same transform,
136*6fd4391dSSanjay Patel       // but any code movement would be within the same block.
137*6fd4391dSSanjay Patel 
138*6fd4391dSSanjay Patel       if (!DivDominates)
139*6fd4391dSSanjay Patel         DivInst->moveBefore(RemInst);
140*6fd4391dSSanjay Patel       Mul->insertAfter(RemInst);
141*6fd4391dSSanjay Patel       Sub->insertAfter(Mul);
142*6fd4391dSSanjay Patel 
143*6fd4391dSSanjay Patel       // Now kill the explicit remainder. We have replaced it with:
144*6fd4391dSSanjay Patel       // (sub X, (mul (div X, Y), Y)
145*6fd4391dSSanjay Patel       RemInst->replaceAllUsesWith(Sub);
146*6fd4391dSSanjay Patel       RemInst->eraseFromParent();
147*6fd4391dSSanjay Patel       NumDecomposed++;
148*6fd4391dSSanjay Patel     }
149*6fd4391dSSanjay Patel     Changed = true;
150*6fd4391dSSanjay Patel   }
151*6fd4391dSSanjay Patel 
152*6fd4391dSSanjay Patel   return Changed;
153*6fd4391dSSanjay Patel }
154*6fd4391dSSanjay Patel 
155*6fd4391dSSanjay Patel // Pass manager boilerplate below here.
156*6fd4391dSSanjay Patel 
157*6fd4391dSSanjay Patel namespace {
158*6fd4391dSSanjay Patel struct DivRemPairsLegacyPass : public FunctionPass {
159*6fd4391dSSanjay Patel   static char ID;
160*6fd4391dSSanjay Patel   DivRemPairsLegacyPass() : FunctionPass(ID) {
161*6fd4391dSSanjay Patel     initializeDivRemPairsLegacyPassPass(*PassRegistry::getPassRegistry());
162*6fd4391dSSanjay Patel   }
163*6fd4391dSSanjay Patel 
164*6fd4391dSSanjay Patel   void getAnalysisUsage(AnalysisUsage &AU) const override {
165*6fd4391dSSanjay Patel     AU.addRequired<DominatorTreeWrapperPass>();
166*6fd4391dSSanjay Patel     AU.addRequired<TargetTransformInfoWrapperPass>();
167*6fd4391dSSanjay Patel     AU.setPreservesCFG();
168*6fd4391dSSanjay Patel     AU.addPreserved<DominatorTreeWrapperPass>();
169*6fd4391dSSanjay Patel     AU.addPreserved<GlobalsAAWrapperPass>();
170*6fd4391dSSanjay Patel     FunctionPass::getAnalysisUsage(AU);
171*6fd4391dSSanjay Patel   }
172*6fd4391dSSanjay Patel 
173*6fd4391dSSanjay Patel   bool runOnFunction(Function &F) override {
174*6fd4391dSSanjay Patel     if (skipFunction(F))
175*6fd4391dSSanjay Patel       return false;
176*6fd4391dSSanjay Patel     auto &TTI = getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
177*6fd4391dSSanjay Patel     auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
178*6fd4391dSSanjay Patel     return optimizeDivRem(F, TTI, DT);
179*6fd4391dSSanjay Patel   }
180*6fd4391dSSanjay Patel };
181*6fd4391dSSanjay Patel }
182*6fd4391dSSanjay Patel 
183*6fd4391dSSanjay Patel char DivRemPairsLegacyPass::ID = 0;
184*6fd4391dSSanjay Patel INITIALIZE_PASS_BEGIN(DivRemPairsLegacyPass, "div-rem-pairs",
185*6fd4391dSSanjay Patel                       "Hoist/decompose integer division and remainder", false,
186*6fd4391dSSanjay Patel                       false)
187*6fd4391dSSanjay Patel INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
188*6fd4391dSSanjay Patel INITIALIZE_PASS_END(DivRemPairsLegacyPass, "div-rem-pairs",
189*6fd4391dSSanjay Patel                     "Hoist/decompose integer division and remainder", false,
190*6fd4391dSSanjay Patel                     false)
191*6fd4391dSSanjay Patel FunctionPass *llvm::createDivRemPairsPass() {
192*6fd4391dSSanjay Patel   return new DivRemPairsLegacyPass();
193*6fd4391dSSanjay Patel }
194*6fd4391dSSanjay Patel 
195*6fd4391dSSanjay Patel PreservedAnalyses DivRemPairsPass::run(Function &F,
196*6fd4391dSSanjay Patel                                        FunctionAnalysisManager &FAM) {
197*6fd4391dSSanjay Patel   TargetTransformInfo &TTI = FAM.getResult<TargetIRAnalysis>(F);
198*6fd4391dSSanjay Patel   DominatorTree &DT = FAM.getResult<DominatorTreeAnalysis>(F);
199*6fd4391dSSanjay Patel   if (!optimizeDivRem(F, TTI, DT))
200*6fd4391dSSanjay Patel     return PreservedAnalyses::all();
201*6fd4391dSSanjay Patel   // TODO: This pass just hoists/replaces math ops - all analyses are preserved?
202*6fd4391dSSanjay Patel   PreservedAnalyses PA;
203*6fd4391dSSanjay Patel   PA.preserveSet<CFGAnalyses>();
204*6fd4391dSSanjay Patel   PA.preserve<GlobalsAA>();
205*6fd4391dSSanjay Patel   return PA;
206*6fd4391dSSanjay Patel }
207