18e0cf076SRoman Lebedev //===- DivRemPairs.cpp - Hoist/decompose division and remainder -*- C++ -*-===//
26fd4391dSSanjay Patel //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66fd4391dSSanjay Patel //
76fd4391dSSanjay Patel //===----------------------------------------------------------------------===//
86fd4391dSSanjay Patel //
98e0cf076SRoman Lebedev // This pass hoists and/or decomposes integer division and remainder
106fd4391dSSanjay Patel // instructions to enable CFG improvements and better codegen.
116fd4391dSSanjay Patel //
126fd4391dSSanjay Patel //===----------------------------------------------------------------------===//
136fd4391dSSanjay Patel 
146fd4391dSSanjay Patel #include "llvm/Transforms/Scalar/DivRemPairs.h"
152af5f3c1SGeoff Berry #include "llvm/ADT/DenseMap.h"
162af5f3c1SGeoff Berry #include "llvm/ADT/MapVector.h"
176fd4391dSSanjay Patel #include "llvm/ADT/Statistic.h"
186fd4391dSSanjay Patel #include "llvm/Analysis/GlobalsModRef.h"
196fd4391dSSanjay Patel #include "llvm/Analysis/TargetTransformInfo.h"
206fd4391dSSanjay Patel #include "llvm/IR/Dominators.h"
216fd4391dSSanjay Patel #include "llvm/IR/Function.h"
226fd4391dSSanjay Patel #include "llvm/Pass.h"
23213d1d23SGeorge Burgess IV #include "llvm/Support/DebugCounter.h"
246fd4391dSSanjay Patel #include "llvm/Transforms/Scalar.h"
256fd4391dSSanjay Patel #include "llvm/Transforms/Utils/BypassSlowDivision.h"
26*5f616901SRoman Lebedev 
276fd4391dSSanjay Patel using namespace llvm;
286fd4391dSSanjay Patel 
296fd4391dSSanjay Patel #define DEBUG_TYPE "div-rem-pairs"
306fd4391dSSanjay Patel STATISTIC(NumPairs, "Number of div/rem pairs");
316fd4391dSSanjay Patel STATISTIC(NumHoisted, "Number of instructions hoisted");
326fd4391dSSanjay Patel STATISTIC(NumDecomposed, "Number of instructions decomposed");
33213d1d23SGeorge Burgess IV DEBUG_COUNTER(DRPCounter, "div-rem-pairs-transform",
34213d1d23SGeorge Burgess IV               "Controls transformations in div-rem-pairs pass");
356fd4391dSSanjay Patel 
36*5f616901SRoman Lebedev /// A thin wrapper to store two values that we matched as div-rem pair.
37*5f616901SRoman Lebedev /// We want this extra indirection to avoid dealing with RAUW'ing the map keys.
38*5f616901SRoman Lebedev struct DivRemPairWorklistEntry {
39*5f616901SRoman Lebedev   /// The actual udiv/sdiv instruction. Source of truth.
40*5f616901SRoman Lebedev   AssertingVH<Instruction> DivInst;
416fd4391dSSanjay Patel 
42*5f616901SRoman Lebedev   /// The instruction that we have matched as a remainder instruction.
43*5f616901SRoman Lebedev   /// Should only be used as Value, don't introspect it.
44*5f616901SRoman Lebedev   AssertingVH<Instruction> RemInst;
45*5f616901SRoman Lebedev 
46*5f616901SRoman Lebedev   DivRemPairWorklistEntry(Instruction *DivInst_, Instruction *RemInst_)
47*5f616901SRoman Lebedev       : DivInst(DivInst_), RemInst(RemInst_) {
48*5f616901SRoman Lebedev     assert((DivInst->getOpcode() == Instruction::UDiv ||
49*5f616901SRoman Lebedev             DivInst->getOpcode() == Instruction::SDiv) &&
50*5f616901SRoman Lebedev            "Not a division.");
51*5f616901SRoman Lebedev     assert(DivInst->getType() == RemInst->getType() && "Types should match.");
52*5f616901SRoman Lebedev     // We can't check anything else about remainder instruction,
53*5f616901SRoman Lebedev     // it's not strictly required to be a urem/srem.
54*5f616901SRoman Lebedev   }
55*5f616901SRoman Lebedev 
56*5f616901SRoman Lebedev   /// The type for this pair, identical for both the div and rem.
57*5f616901SRoman Lebedev   Type *getType() const { return DivInst->getType(); }
58*5f616901SRoman Lebedev 
59*5f616901SRoman Lebedev   /// Is this pair signed or unsigned?
60*5f616901SRoman Lebedev   bool isSigned() const { return DivInst->getOpcode() == Instruction::SDiv; }
61*5f616901SRoman Lebedev 
62*5f616901SRoman Lebedev   /// In this pair, what are the divident and divisor?
63*5f616901SRoman Lebedev   Value *getDividend() const { return DivInst->getOperand(0); }
64*5f616901SRoman Lebedev   Value *getDivisor() const { return DivInst->getOperand(1); }
65*5f616901SRoman Lebedev };
66*5f616901SRoman Lebedev using DivRemWorklistTy = SmallVector<DivRemPairWorklistEntry, 4>;
67*5f616901SRoman Lebedev 
68*5f616901SRoman Lebedev /// Find matching pairs of integer div/rem ops (they have the same numerator,
69*5f616901SRoman Lebedev /// denominator, and signedness). Place those pairs into a worklist for further
70*5f616901SRoman Lebedev /// processing. This indirection is needed because we have to use TrackingVH<>
71*5f616901SRoman Lebedev /// because we will be doing RAUW, and if one of the rem instructions we change
72*5f616901SRoman Lebedev /// happens to be an input to another div/rem in the maps, we'd have problems.
73*5f616901SRoman Lebedev static DivRemWorklistTy getWorklist(Function &F) {
746fd4391dSSanjay Patel   // Insert all divide and remainder instructions into maps keyed by their
756fd4391dSSanjay Patel   // operands and opcode (signed or unsigned).
762af5f3c1SGeoff Berry   DenseMap<DivRemMapKey, Instruction *> DivMap;
772af5f3c1SGeoff Berry   // Use a MapVector for RemMap so that instructions are moved/inserted in a
782af5f3c1SGeoff Berry   // deterministic order.
798e0cf076SRoman Lebedev   MapVector<DivRemMapKey, Instruction *> RemMap;
806fd4391dSSanjay Patel   for (auto &BB : F) {
816fd4391dSSanjay Patel     for (auto &I : BB) {
826fd4391dSSanjay Patel       if (I.getOpcode() == Instruction::SDiv)
836fd4391dSSanjay Patel         DivMap[DivRemMapKey(true, I.getOperand(0), I.getOperand(1))] = &I;
846fd4391dSSanjay Patel       else if (I.getOpcode() == Instruction::UDiv)
856fd4391dSSanjay Patel         DivMap[DivRemMapKey(false, I.getOperand(0), I.getOperand(1))] = &I;
866fd4391dSSanjay Patel       else if (I.getOpcode() == Instruction::SRem)
878e0cf076SRoman Lebedev         RemMap[DivRemMapKey(true, I.getOperand(0), I.getOperand(1))] = &I;
886fd4391dSSanjay Patel       else if (I.getOpcode() == Instruction::URem)
898e0cf076SRoman Lebedev         RemMap[DivRemMapKey(false, I.getOperand(0), I.getOperand(1))] = &I;
906fd4391dSSanjay Patel     }
916fd4391dSSanjay Patel   }
926fd4391dSSanjay Patel 
93*5f616901SRoman Lebedev   // We'll accumulate the matching pairs of div-rem instructions here.
94*5f616901SRoman Lebedev   DivRemWorklistTy Worklist;
95*5f616901SRoman Lebedev 
966fd4391dSSanjay Patel   // We can iterate over either map because we are only looking for matched
976fd4391dSSanjay Patel   // pairs. Choose remainders for efficiency because they are usually even more
986fd4391dSSanjay Patel   // rare than division.
996fd4391dSSanjay Patel   for (auto &RemPair : RemMap) {
1006fd4391dSSanjay Patel     // Find the matching division instruction from the division map.
1012af5f3c1SGeoff Berry     Instruction *DivInst = DivMap[RemPair.first];
1026fd4391dSSanjay Patel     if (!DivInst)
1036fd4391dSSanjay Patel       continue;
1046fd4391dSSanjay Patel 
105*5f616901SRoman Lebedev     // We have a matching pair of div/rem instructions.
1066fd4391dSSanjay Patel     NumPairs++;
1078e0cf076SRoman Lebedev     Instruction *RemInst = RemPair.second;
108*5f616901SRoman Lebedev 
109*5f616901SRoman Lebedev     // Place it in the worklist.
110*5f616901SRoman Lebedev     Worklist.emplace_back(DivInst, RemInst);
111*5f616901SRoman Lebedev   }
112*5f616901SRoman Lebedev 
113*5f616901SRoman Lebedev   return Worklist;
114*5f616901SRoman Lebedev }
115*5f616901SRoman Lebedev 
116*5f616901SRoman Lebedev /// Find matching pairs of integer div/rem ops (they have the same numerator,
117*5f616901SRoman Lebedev /// denominator, and signedness). If they exist in different basic blocks, bring
118*5f616901SRoman Lebedev /// them together by hoisting or replace the common division operation that is
119*5f616901SRoman Lebedev /// implicit in the remainder:
120*5f616901SRoman Lebedev /// X % Y <--> X - ((X / Y) * Y).
121*5f616901SRoman Lebedev ///
122*5f616901SRoman Lebedev /// We can largely ignore the normal safety and cost constraints on speculation
123*5f616901SRoman Lebedev /// of these ops when we find a matching pair. This is because we are already
124*5f616901SRoman Lebedev /// guaranteed that any exceptions and most cost are already incurred by the
125*5f616901SRoman Lebedev /// first member of the pair.
126*5f616901SRoman Lebedev ///
127*5f616901SRoman Lebedev /// Note: This transform could be an oddball enhancement to EarlyCSE, GVN, or
128*5f616901SRoman Lebedev /// SimplifyCFG, but it's split off on its own because it's different enough
129*5f616901SRoman Lebedev /// that it doesn't quite match the stated objectives of those passes.
130*5f616901SRoman Lebedev static bool optimizeDivRem(Function &F, const TargetTransformInfo &TTI,
131*5f616901SRoman Lebedev                            const DominatorTree &DT) {
132*5f616901SRoman Lebedev   bool Changed = false;
133*5f616901SRoman Lebedev 
134*5f616901SRoman Lebedev   // Get the matching pairs of div-rem instructions. We want this extra
135*5f616901SRoman Lebedev   // indirection to avoid dealing with having to RAUW the keys of the maps.
136*5f616901SRoman Lebedev   DivRemWorklistTy Worklist = getWorklist(F);
137*5f616901SRoman Lebedev 
138*5f616901SRoman Lebedev   // Process each entry in the worklist.
139*5f616901SRoman Lebedev   for (DivRemPairWorklistEntry &E : Worklist) {
140*5f616901SRoman Lebedev     bool HasDivRemOp = TTI.hasDivRemOp(E.getType(), E.isSigned());
141*5f616901SRoman Lebedev 
142*5f616901SRoman Lebedev     auto &DivInst = E.DivInst;
143*5f616901SRoman Lebedev     auto &RemInst = E.RemInst;
1446fd4391dSSanjay Patel 
1456fd4391dSSanjay Patel     // If the target supports div+rem and the instructions are in the same block
1466fd4391dSSanjay Patel     // already, there's nothing to do. The backend should handle this. If the
1476fd4391dSSanjay Patel     // target does not support div+rem, then we will decompose the rem.
1486fd4391dSSanjay Patel     if (HasDivRemOp && RemInst->getParent() == DivInst->getParent())
1496fd4391dSSanjay Patel       continue;
1506fd4391dSSanjay Patel 
1516fd4391dSSanjay Patel     bool DivDominates = DT.dominates(DivInst, RemInst);
1528e0cf076SRoman Lebedev     if (!DivDominates && !DT.dominates(RemInst, DivInst))
1536fd4391dSSanjay Patel       continue;
1546fd4391dSSanjay Patel 
1558e0cf076SRoman Lebedev     if (!DebugCounter::shouldExecute(DRPCounter))
156213d1d23SGeorge Burgess IV       continue;
157213d1d23SGeorge Burgess IV 
1586fd4391dSSanjay Patel     if (HasDivRemOp) {
1596fd4391dSSanjay Patel       // The target has a single div/rem operation. Hoist the lower instruction
1606fd4391dSSanjay Patel       // to make the matched pair visible to the backend.
1616fd4391dSSanjay Patel       if (DivDominates)
1626fd4391dSSanjay Patel         RemInst->moveAfter(DivInst);
1636fd4391dSSanjay Patel       else
1646fd4391dSSanjay Patel         DivInst->moveAfter(RemInst);
1656fd4391dSSanjay Patel       NumHoisted++;
1666fd4391dSSanjay Patel     } else {
1678e0cf076SRoman Lebedev       // The target does not have a single div/rem operation. Decompose the
1688e0cf076SRoman Lebedev       // remainder calculation as:
1696fd4391dSSanjay Patel       // X % Y --> X - ((X / Y) * Y).
170*5f616901SRoman Lebedev       Value *X = E.getDividend();
171*5f616901SRoman Lebedev       Value *Y = E.getDivisor();
1726fd4391dSSanjay Patel       Instruction *Mul = BinaryOperator::CreateMul(DivInst, Y);
1736fd4391dSSanjay Patel       Instruction *Sub = BinaryOperator::CreateSub(X, Mul);
1746fd4391dSSanjay Patel 
1756fd4391dSSanjay Patel       // If the remainder dominates, then hoist the division up to that block:
1766fd4391dSSanjay Patel       //
1776fd4391dSSanjay Patel       // bb1:
1786fd4391dSSanjay Patel       //   %rem = srem %x, %y
1796fd4391dSSanjay Patel       // bb2:
1806fd4391dSSanjay Patel       //   %div = sdiv %x, %y
1816fd4391dSSanjay Patel       // -->
1826fd4391dSSanjay Patel       // bb1:
1836fd4391dSSanjay Patel       //   %div = sdiv %x, %y
1846fd4391dSSanjay Patel       //   %mul = mul %div, %y
1856fd4391dSSanjay Patel       //   %rem = sub %x, %mul
1866fd4391dSSanjay Patel       //
1876fd4391dSSanjay Patel       // If the division dominates, it's already in the right place. The mul+sub
1886fd4391dSSanjay Patel       // will be in a different block because we don't assume that they are
1896fd4391dSSanjay Patel       // cheap to speculatively execute:
1906fd4391dSSanjay Patel       //
1916fd4391dSSanjay Patel       // bb1:
1926fd4391dSSanjay Patel       //   %div = sdiv %x, %y
1936fd4391dSSanjay Patel       // bb2:
1946fd4391dSSanjay Patel       //   %rem = srem %x, %y
1956fd4391dSSanjay Patel       // -->
1966fd4391dSSanjay Patel       // bb1:
1976fd4391dSSanjay Patel       //   %div = sdiv %x, %y
1986fd4391dSSanjay Patel       // bb2:
1996fd4391dSSanjay Patel       //   %mul = mul %div, %y
2006fd4391dSSanjay Patel       //   %rem = sub %x, %mul
2016fd4391dSSanjay Patel       //
2026fd4391dSSanjay Patel       // If the div and rem are in the same block, we do the same transform,
2036fd4391dSSanjay Patel       // but any code movement would be within the same block.
2046fd4391dSSanjay Patel 
2056fd4391dSSanjay Patel       if (!DivDominates)
2066fd4391dSSanjay Patel         DivInst->moveBefore(RemInst);
2076fd4391dSSanjay Patel       Mul->insertAfter(RemInst);
2086fd4391dSSanjay Patel       Sub->insertAfter(Mul);
2096fd4391dSSanjay Patel 
2106fd4391dSSanjay Patel       // Now kill the explicit remainder. We have replaced it with:
2116fd4391dSSanjay Patel       // (sub X, (mul (div X, Y), Y)
212*5f616901SRoman Lebedev       Sub->setName(RemInst->getName() + ".decomposed");
213*5f616901SRoman Lebedev       Instruction *OrigRemInst = RemInst;
214*5f616901SRoman Lebedev       // Update AssertingVH<> with new instruction so it doesn't assert.
215*5f616901SRoman Lebedev       RemInst = Sub;
216*5f616901SRoman Lebedev       // And replace the original instruction with the new one.
217*5f616901SRoman Lebedev       OrigRemInst->replaceAllUsesWith(Sub);
218*5f616901SRoman Lebedev       OrigRemInst->eraseFromParent();
2196fd4391dSSanjay Patel       NumDecomposed++;
2206fd4391dSSanjay Patel     }
2216fd4391dSSanjay Patel     Changed = true;
2226fd4391dSSanjay Patel   }
2236fd4391dSSanjay Patel 
2246fd4391dSSanjay Patel   return Changed;
2256fd4391dSSanjay Patel }
2266fd4391dSSanjay Patel 
2276fd4391dSSanjay Patel // Pass manager boilerplate below here.
2286fd4391dSSanjay Patel 
2296fd4391dSSanjay Patel namespace {
2306fd4391dSSanjay Patel struct DivRemPairsLegacyPass : public FunctionPass {
2316fd4391dSSanjay Patel   static char ID;
2326fd4391dSSanjay Patel   DivRemPairsLegacyPass() : FunctionPass(ID) {
2336fd4391dSSanjay Patel     initializeDivRemPairsLegacyPassPass(*PassRegistry::getPassRegistry());
2346fd4391dSSanjay Patel   }
2356fd4391dSSanjay Patel 
2366fd4391dSSanjay Patel   void getAnalysisUsage(AnalysisUsage &AU) const override {
2376fd4391dSSanjay Patel     AU.addRequired<DominatorTreeWrapperPass>();
2386fd4391dSSanjay Patel     AU.addRequired<TargetTransformInfoWrapperPass>();
2396fd4391dSSanjay Patel     AU.setPreservesCFG();
2406fd4391dSSanjay Patel     AU.addPreserved<DominatorTreeWrapperPass>();
2416fd4391dSSanjay Patel     AU.addPreserved<GlobalsAAWrapperPass>();
2426fd4391dSSanjay Patel     FunctionPass::getAnalysisUsage(AU);
2436fd4391dSSanjay Patel   }
2446fd4391dSSanjay Patel 
2456fd4391dSSanjay Patel   bool runOnFunction(Function &F) override {
2466fd4391dSSanjay Patel     if (skipFunction(F))
2476fd4391dSSanjay Patel       return false;
2486fd4391dSSanjay Patel     auto &TTI = getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
2496fd4391dSSanjay Patel     auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
2506fd4391dSSanjay Patel     return optimizeDivRem(F, TTI, DT);
2516fd4391dSSanjay Patel   }
2526fd4391dSSanjay Patel };
253*5f616901SRoman Lebedev } // namespace
2546fd4391dSSanjay Patel 
2556fd4391dSSanjay Patel char DivRemPairsLegacyPass::ID = 0;
2566fd4391dSSanjay Patel INITIALIZE_PASS_BEGIN(DivRemPairsLegacyPass, "div-rem-pairs",
2576fd4391dSSanjay Patel                       "Hoist/decompose integer division and remainder", false,
2586fd4391dSSanjay Patel                       false)
2596fd4391dSSanjay Patel INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
2606fd4391dSSanjay Patel INITIALIZE_PASS_END(DivRemPairsLegacyPass, "div-rem-pairs",
2616fd4391dSSanjay Patel                     "Hoist/decompose integer division and remainder", false,
2626fd4391dSSanjay Patel                     false)
2636fd4391dSSanjay Patel FunctionPass *llvm::createDivRemPairsPass() {
2646fd4391dSSanjay Patel   return new DivRemPairsLegacyPass();
2656fd4391dSSanjay Patel }
2666fd4391dSSanjay Patel 
2676fd4391dSSanjay Patel PreservedAnalyses DivRemPairsPass::run(Function &F,
2686fd4391dSSanjay Patel                                        FunctionAnalysisManager &FAM) {
2696fd4391dSSanjay Patel   TargetTransformInfo &TTI = FAM.getResult<TargetIRAnalysis>(F);
2706fd4391dSSanjay Patel   DominatorTree &DT = FAM.getResult<DominatorTreeAnalysis>(F);
2716fd4391dSSanjay Patel   if (!optimizeDivRem(F, TTI, DT))
2726fd4391dSSanjay Patel     return PreservedAnalyses::all();
2736fd4391dSSanjay Patel   // TODO: This pass just hoists/replaces math ops - all analyses are preserved?
2746fd4391dSSanjay Patel   PreservedAnalyses PA;
2756fd4391dSSanjay Patel   PA.preserveSet<CFGAnalyses>();
2766fd4391dSSanjay Patel   PA.preserve<GlobalsAA>();
2776fd4391dSSanjay Patel   return PA;
2786fd4391dSSanjay Patel }
279