16fd4391dSSanjay Patel //===- DivRemPairs.cpp - Hoist/decompose division and remainder -*- C++ -*-===//
26fd4391dSSanjay Patel //
36fd4391dSSanjay Patel //                     The LLVM Compiler Infrastructure
46fd4391dSSanjay Patel //
56fd4391dSSanjay Patel // This file is distributed under the University of Illinois Open Source
66fd4391dSSanjay Patel // License. See LICENSE.TXT for details.
76fd4391dSSanjay Patel //
86fd4391dSSanjay Patel //===----------------------------------------------------------------------===//
96fd4391dSSanjay Patel //
106fd4391dSSanjay Patel // This pass hoists and/or decomposes integer division and remainder
116fd4391dSSanjay Patel // instructions to enable CFG improvements and better codegen.
126fd4391dSSanjay Patel //
136fd4391dSSanjay Patel //===----------------------------------------------------------------------===//
146fd4391dSSanjay Patel 
156fd4391dSSanjay Patel #include "llvm/Transforms/Scalar/DivRemPairs.h"
16*2af5f3c1SGeoff Berry #include "llvm/ADT/DenseMap.h"
17*2af5f3c1SGeoff Berry #include "llvm/ADT/MapVector.h"
186fd4391dSSanjay Patel #include "llvm/ADT/Statistic.h"
196fd4391dSSanjay Patel #include "llvm/Analysis/GlobalsModRef.h"
206fd4391dSSanjay Patel #include "llvm/Analysis/TargetTransformInfo.h"
216fd4391dSSanjay Patel #include "llvm/IR/Dominators.h"
226fd4391dSSanjay Patel #include "llvm/IR/Function.h"
236fd4391dSSanjay Patel #include "llvm/Pass.h"
246fd4391dSSanjay Patel #include "llvm/Transforms/Scalar.h"
256fd4391dSSanjay Patel #include "llvm/Transforms/Utils/BypassSlowDivision.h"
266fd4391dSSanjay Patel using namespace llvm;
276fd4391dSSanjay Patel 
286fd4391dSSanjay Patel #define DEBUG_TYPE "div-rem-pairs"
296fd4391dSSanjay Patel STATISTIC(NumPairs, "Number of div/rem pairs");
306fd4391dSSanjay Patel STATISTIC(NumHoisted, "Number of instructions hoisted");
316fd4391dSSanjay Patel STATISTIC(NumDecomposed, "Number of instructions decomposed");
326fd4391dSSanjay Patel 
336fd4391dSSanjay Patel /// Find matching pairs of integer div/rem ops (they have the same numerator,
346fd4391dSSanjay Patel /// denominator, and signedness). If they exist in different basic blocks, bring
356fd4391dSSanjay Patel /// them together by hoisting or replace the common division operation that is
366fd4391dSSanjay Patel /// implicit in the remainder:
376fd4391dSSanjay Patel /// X % Y <--> X - ((X / Y) * Y).
386fd4391dSSanjay Patel ///
396fd4391dSSanjay Patel /// We can largely ignore the normal safety and cost constraints on speculation
406fd4391dSSanjay Patel /// of these ops when we find a matching pair. This is because we are already
416fd4391dSSanjay Patel /// guaranteed that any exceptions and most cost are already incurred by the
426fd4391dSSanjay Patel /// first member of the pair.
436fd4391dSSanjay Patel ///
446fd4391dSSanjay Patel /// Note: This transform could be an oddball enhancement to EarlyCSE, GVN, or
456fd4391dSSanjay Patel /// SimplifyCFG, but it's split off on its own because it's different enough
466fd4391dSSanjay Patel /// that it doesn't quite match the stated objectives of those passes.
476fd4391dSSanjay Patel static bool optimizeDivRem(Function &F, const TargetTransformInfo &TTI,
486fd4391dSSanjay Patel                            const DominatorTree &DT) {
496fd4391dSSanjay Patel   bool Changed = false;
506fd4391dSSanjay Patel 
516fd4391dSSanjay Patel   // Insert all divide and remainder instructions into maps keyed by their
526fd4391dSSanjay Patel   // operands and opcode (signed or unsigned).
53*2af5f3c1SGeoff Berry   DenseMap<DivRemMapKey, Instruction *> DivMap;
54*2af5f3c1SGeoff Berry   // Use a MapVector for RemMap so that instructions are moved/inserted in a
55*2af5f3c1SGeoff Berry   // deterministic order.
56*2af5f3c1SGeoff Berry   MapVector<DivRemMapKey, Instruction *> RemMap;
576fd4391dSSanjay Patel   for (auto &BB : F) {
586fd4391dSSanjay Patel     for (auto &I : BB) {
596fd4391dSSanjay Patel       if (I.getOpcode() == Instruction::SDiv)
606fd4391dSSanjay Patel         DivMap[DivRemMapKey(true, I.getOperand(0), I.getOperand(1))] = &I;
616fd4391dSSanjay Patel       else if (I.getOpcode() == Instruction::UDiv)
626fd4391dSSanjay Patel         DivMap[DivRemMapKey(false, I.getOperand(0), I.getOperand(1))] = &I;
636fd4391dSSanjay Patel       else if (I.getOpcode() == Instruction::SRem)
646fd4391dSSanjay Patel         RemMap[DivRemMapKey(true, I.getOperand(0), I.getOperand(1))] = &I;
656fd4391dSSanjay Patel       else if (I.getOpcode() == Instruction::URem)
666fd4391dSSanjay Patel         RemMap[DivRemMapKey(false, I.getOperand(0), I.getOperand(1))] = &I;
676fd4391dSSanjay Patel     }
686fd4391dSSanjay Patel   }
696fd4391dSSanjay Patel 
706fd4391dSSanjay Patel   // We can iterate over either map because we are only looking for matched
716fd4391dSSanjay Patel   // pairs. Choose remainders for efficiency because they are usually even more
726fd4391dSSanjay Patel   // rare than division.
736fd4391dSSanjay Patel   for (auto &RemPair : RemMap) {
746fd4391dSSanjay Patel     // Find the matching division instruction from the division map.
75*2af5f3c1SGeoff Berry     Instruction *DivInst = DivMap[RemPair.first];
766fd4391dSSanjay Patel     if (!DivInst)
776fd4391dSSanjay Patel       continue;
786fd4391dSSanjay Patel 
796fd4391dSSanjay Patel     // We have a matching pair of div/rem instructions. If one dominates the
806fd4391dSSanjay Patel     // other, hoist and/or replace one.
816fd4391dSSanjay Patel     NumPairs++;
82*2af5f3c1SGeoff Berry     Instruction *RemInst = RemPair.second;
836fd4391dSSanjay Patel     bool IsSigned = DivInst->getOpcode() == Instruction::SDiv;
846fd4391dSSanjay Patel     bool HasDivRemOp = TTI.hasDivRemOp(DivInst->getType(), IsSigned);
856fd4391dSSanjay Patel 
866fd4391dSSanjay Patel     // If the target supports div+rem and the instructions are in the same block
876fd4391dSSanjay Patel     // already, there's nothing to do. The backend should handle this. If the
886fd4391dSSanjay Patel     // target does not support div+rem, then we will decompose the rem.
896fd4391dSSanjay Patel     if (HasDivRemOp && RemInst->getParent() == DivInst->getParent())
906fd4391dSSanjay Patel       continue;
916fd4391dSSanjay Patel 
926fd4391dSSanjay Patel     bool DivDominates = DT.dominates(DivInst, RemInst);
936fd4391dSSanjay Patel     if (!DivDominates && !DT.dominates(RemInst, DivInst))
946fd4391dSSanjay Patel       continue;
956fd4391dSSanjay Patel 
966fd4391dSSanjay Patel     if (HasDivRemOp) {
976fd4391dSSanjay Patel       // The target has a single div/rem operation. Hoist the lower instruction
986fd4391dSSanjay Patel       // to make the matched pair visible to the backend.
996fd4391dSSanjay Patel       if (DivDominates)
1006fd4391dSSanjay Patel         RemInst->moveAfter(DivInst);
1016fd4391dSSanjay Patel       else
1026fd4391dSSanjay Patel         DivInst->moveAfter(RemInst);
1036fd4391dSSanjay Patel       NumHoisted++;
1046fd4391dSSanjay Patel     } else {
1056fd4391dSSanjay Patel       // The target does not have a single div/rem operation. Decompose the
1066fd4391dSSanjay Patel       // remainder calculation as:
1076fd4391dSSanjay Patel       // X % Y --> X - ((X / Y) * Y).
1086fd4391dSSanjay Patel       Value *X = RemInst->getOperand(0);
1096fd4391dSSanjay Patel       Value *Y = RemInst->getOperand(1);
1106fd4391dSSanjay Patel       Instruction *Mul = BinaryOperator::CreateMul(DivInst, Y);
1116fd4391dSSanjay Patel       Instruction *Sub = BinaryOperator::CreateSub(X, Mul);
1126fd4391dSSanjay Patel 
1136fd4391dSSanjay Patel       // If the remainder dominates, then hoist the division up to that block:
1146fd4391dSSanjay Patel       //
1156fd4391dSSanjay Patel       // bb1:
1166fd4391dSSanjay Patel       //   %rem = srem %x, %y
1176fd4391dSSanjay Patel       // bb2:
1186fd4391dSSanjay Patel       //   %div = sdiv %x, %y
1196fd4391dSSanjay Patel       // -->
1206fd4391dSSanjay Patel       // bb1:
1216fd4391dSSanjay Patel       //   %div = sdiv %x, %y
1226fd4391dSSanjay Patel       //   %mul = mul %div, %y
1236fd4391dSSanjay Patel       //   %rem = sub %x, %mul
1246fd4391dSSanjay Patel       //
1256fd4391dSSanjay Patel       // If the division dominates, it's already in the right place. The mul+sub
1266fd4391dSSanjay Patel       // will be in a different block because we don't assume that they are
1276fd4391dSSanjay Patel       // cheap to speculatively execute:
1286fd4391dSSanjay Patel       //
1296fd4391dSSanjay Patel       // bb1:
1306fd4391dSSanjay Patel       //   %div = sdiv %x, %y
1316fd4391dSSanjay Patel       // bb2:
1326fd4391dSSanjay Patel       //   %rem = srem %x, %y
1336fd4391dSSanjay Patel       // -->
1346fd4391dSSanjay Patel       // bb1:
1356fd4391dSSanjay Patel       //   %div = sdiv %x, %y
1366fd4391dSSanjay Patel       // bb2:
1376fd4391dSSanjay Patel       //   %mul = mul %div, %y
1386fd4391dSSanjay Patel       //   %rem = sub %x, %mul
1396fd4391dSSanjay Patel       //
1406fd4391dSSanjay Patel       // If the div and rem are in the same block, we do the same transform,
1416fd4391dSSanjay Patel       // but any code movement would be within the same block.
1426fd4391dSSanjay Patel 
1436fd4391dSSanjay Patel       if (!DivDominates)
1446fd4391dSSanjay Patel         DivInst->moveBefore(RemInst);
1456fd4391dSSanjay Patel       Mul->insertAfter(RemInst);
1466fd4391dSSanjay Patel       Sub->insertAfter(Mul);
1476fd4391dSSanjay Patel 
1486fd4391dSSanjay Patel       // Now kill the explicit remainder. We have replaced it with:
1496fd4391dSSanjay Patel       // (sub X, (mul (div X, Y), Y)
1506fd4391dSSanjay Patel       RemInst->replaceAllUsesWith(Sub);
1516fd4391dSSanjay Patel       RemInst->eraseFromParent();
1526fd4391dSSanjay Patel       NumDecomposed++;
1536fd4391dSSanjay Patel     }
1546fd4391dSSanjay Patel     Changed = true;
1556fd4391dSSanjay Patel   }
1566fd4391dSSanjay Patel 
1576fd4391dSSanjay Patel   return Changed;
1586fd4391dSSanjay Patel }
1596fd4391dSSanjay Patel 
1606fd4391dSSanjay Patel // Pass manager boilerplate below here.
1616fd4391dSSanjay Patel 
1626fd4391dSSanjay Patel namespace {
1636fd4391dSSanjay Patel struct DivRemPairsLegacyPass : public FunctionPass {
1646fd4391dSSanjay Patel   static char ID;
1656fd4391dSSanjay Patel   DivRemPairsLegacyPass() : FunctionPass(ID) {
1666fd4391dSSanjay Patel     initializeDivRemPairsLegacyPassPass(*PassRegistry::getPassRegistry());
1676fd4391dSSanjay Patel   }
1686fd4391dSSanjay Patel 
1696fd4391dSSanjay Patel   void getAnalysisUsage(AnalysisUsage &AU) const override {
1706fd4391dSSanjay Patel     AU.addRequired<DominatorTreeWrapperPass>();
1716fd4391dSSanjay Patel     AU.addRequired<TargetTransformInfoWrapperPass>();
1726fd4391dSSanjay Patel     AU.setPreservesCFG();
1736fd4391dSSanjay Patel     AU.addPreserved<DominatorTreeWrapperPass>();
1746fd4391dSSanjay Patel     AU.addPreserved<GlobalsAAWrapperPass>();
1756fd4391dSSanjay Patel     FunctionPass::getAnalysisUsage(AU);
1766fd4391dSSanjay Patel   }
1776fd4391dSSanjay Patel 
1786fd4391dSSanjay Patel   bool runOnFunction(Function &F) override {
1796fd4391dSSanjay Patel     if (skipFunction(F))
1806fd4391dSSanjay Patel       return false;
1816fd4391dSSanjay Patel     auto &TTI = getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
1826fd4391dSSanjay Patel     auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1836fd4391dSSanjay Patel     return optimizeDivRem(F, TTI, DT);
1846fd4391dSSanjay Patel   }
1856fd4391dSSanjay Patel };
1866fd4391dSSanjay Patel }
1876fd4391dSSanjay Patel 
1886fd4391dSSanjay Patel char DivRemPairsLegacyPass::ID = 0;
1896fd4391dSSanjay Patel INITIALIZE_PASS_BEGIN(DivRemPairsLegacyPass, "div-rem-pairs",
1906fd4391dSSanjay Patel                       "Hoist/decompose integer division and remainder", false,
1916fd4391dSSanjay Patel                       false)
1926fd4391dSSanjay Patel INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
1936fd4391dSSanjay Patel INITIALIZE_PASS_END(DivRemPairsLegacyPass, "div-rem-pairs",
1946fd4391dSSanjay Patel                     "Hoist/decompose integer division and remainder", false,
1956fd4391dSSanjay Patel                     false)
1966fd4391dSSanjay Patel FunctionPass *llvm::createDivRemPairsPass() {
1976fd4391dSSanjay Patel   return new DivRemPairsLegacyPass();
1986fd4391dSSanjay Patel }
1996fd4391dSSanjay Patel 
2006fd4391dSSanjay Patel PreservedAnalyses DivRemPairsPass::run(Function &F,
2016fd4391dSSanjay Patel                                        FunctionAnalysisManager &FAM) {
2026fd4391dSSanjay Patel   TargetTransformInfo &TTI = FAM.getResult<TargetIRAnalysis>(F);
2036fd4391dSSanjay Patel   DominatorTree &DT = FAM.getResult<DominatorTreeAnalysis>(F);
2046fd4391dSSanjay Patel   if (!optimizeDivRem(F, TTI, DT))
2056fd4391dSSanjay Patel     return PreservedAnalyses::all();
2066fd4391dSSanjay Patel   // TODO: This pass just hoists/replaces math ops - all analyses are preserved?
2076fd4391dSSanjay Patel   PreservedAnalyses PA;
2086fd4391dSSanjay Patel   PA.preserveSet<CFGAnalyses>();
2096fd4391dSSanjay Patel   PA.preserve<GlobalsAA>();
2106fd4391dSSanjay Patel   return PA;
2116fd4391dSSanjay Patel }
212