1*8e0cf076SRoman 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 //
9*8e0cf076SRoman 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"
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");
32213d1d23SGeorge Burgess IV DEBUG_COUNTER(DRPCounter, "div-rem-pairs-transform",
33213d1d23SGeorge Burgess IV               "Controls transformations in div-rem-pairs pass");
346fd4391dSSanjay Patel 
356fd4391dSSanjay Patel /// Find matching pairs of integer div/rem ops (they have the same numerator,
366fd4391dSSanjay Patel /// denominator, and signedness). If they exist in different basic blocks, bring
376fd4391dSSanjay Patel /// them together by hoisting or replace the common division operation that is
386fd4391dSSanjay Patel /// implicit in the remainder:
396fd4391dSSanjay Patel /// X % Y <--> X - ((X / Y) * Y).
406fd4391dSSanjay Patel ///
416fd4391dSSanjay Patel /// We can largely ignore the normal safety and cost constraints on speculation
426fd4391dSSanjay Patel /// of these ops when we find a matching pair. This is because we are already
436fd4391dSSanjay Patel /// guaranteed that any exceptions and most cost are already incurred by the
446fd4391dSSanjay Patel /// first member of the pair.
456fd4391dSSanjay Patel ///
466fd4391dSSanjay Patel /// Note: This transform could be an oddball enhancement to EarlyCSE, GVN, or
476fd4391dSSanjay Patel /// SimplifyCFG, but it's split off on its own because it's different enough
486fd4391dSSanjay Patel /// that it doesn't quite match the stated objectives of those passes.
496fd4391dSSanjay Patel static bool optimizeDivRem(Function &F, const TargetTransformInfo &TTI,
506fd4391dSSanjay Patel                            const DominatorTree &DT) {
516fd4391dSSanjay Patel   bool Changed = false;
526fd4391dSSanjay Patel 
536fd4391dSSanjay Patel   // Insert all divide and remainder instructions into maps keyed by their
546fd4391dSSanjay Patel   // operands and opcode (signed or unsigned).
552af5f3c1SGeoff Berry   DenseMap<DivRemMapKey, Instruction *> DivMap;
562af5f3c1SGeoff Berry   // Use a MapVector for RemMap so that instructions are moved/inserted in a
572af5f3c1SGeoff Berry   // deterministic order.
58*8e0cf076SRoman Lebedev   MapVector<DivRemMapKey, Instruction *> RemMap;
596fd4391dSSanjay Patel   for (auto &BB : F) {
606fd4391dSSanjay Patel     for (auto &I : BB) {
616fd4391dSSanjay Patel       if (I.getOpcode() == Instruction::SDiv)
626fd4391dSSanjay Patel         DivMap[DivRemMapKey(true, I.getOperand(0), I.getOperand(1))] = &I;
636fd4391dSSanjay Patel       else if (I.getOpcode() == Instruction::UDiv)
646fd4391dSSanjay Patel         DivMap[DivRemMapKey(false, I.getOperand(0), I.getOperand(1))] = &I;
656fd4391dSSanjay Patel       else if (I.getOpcode() == Instruction::SRem)
66*8e0cf076SRoman Lebedev         RemMap[DivRemMapKey(true, I.getOperand(0), I.getOperand(1))] = &I;
676fd4391dSSanjay Patel       else if (I.getOpcode() == Instruction::URem)
68*8e0cf076SRoman Lebedev         RemMap[DivRemMapKey(false, I.getOperand(0), I.getOperand(1))] = &I;
696fd4391dSSanjay Patel     }
706fd4391dSSanjay Patel   }
716fd4391dSSanjay Patel 
726fd4391dSSanjay Patel   // We can iterate over either map because we are only looking for matched
736fd4391dSSanjay Patel   // pairs. Choose remainders for efficiency because they are usually even more
746fd4391dSSanjay Patel   // rare than division.
756fd4391dSSanjay Patel   for (auto &RemPair : RemMap) {
766fd4391dSSanjay Patel     // Find the matching division instruction from the division map.
772af5f3c1SGeoff Berry     Instruction *DivInst = DivMap[RemPair.first];
786fd4391dSSanjay Patel     if (!DivInst)
796fd4391dSSanjay Patel       continue;
806fd4391dSSanjay Patel 
81*8e0cf076SRoman Lebedev     // We have a matching pair of div/rem instructions. If one dominates the
82*8e0cf076SRoman Lebedev     // other, hoist and/or replace one.
836fd4391dSSanjay Patel     NumPairs++;
84*8e0cf076SRoman Lebedev     Instruction *RemInst = RemPair.second;
85*8e0cf076SRoman Lebedev     bool IsSigned = DivInst->getOpcode() == Instruction::SDiv;
866fd4391dSSanjay Patel     bool HasDivRemOp = TTI.hasDivRemOp(DivInst->getType(), IsSigned);
876fd4391dSSanjay Patel 
886fd4391dSSanjay Patel     // If the target supports div+rem and the instructions are in the same block
896fd4391dSSanjay Patel     // already, there's nothing to do. The backend should handle this. If the
906fd4391dSSanjay Patel     // target does not support div+rem, then we will decompose the rem.
916fd4391dSSanjay Patel     if (HasDivRemOp && RemInst->getParent() == DivInst->getParent())
926fd4391dSSanjay Patel       continue;
936fd4391dSSanjay Patel 
946fd4391dSSanjay Patel     bool DivDominates = DT.dominates(DivInst, RemInst);
95*8e0cf076SRoman Lebedev     if (!DivDominates && !DT.dominates(RemInst, DivInst))
966fd4391dSSanjay Patel       continue;
976fd4391dSSanjay Patel 
98*8e0cf076SRoman Lebedev     if (!DebugCounter::shouldExecute(DRPCounter))
99213d1d23SGeorge Burgess IV       continue;
100213d1d23SGeorge Burgess IV 
1016fd4391dSSanjay Patel     if (HasDivRemOp) {
1026fd4391dSSanjay Patel       // The target has a single div/rem operation. Hoist the lower instruction
1036fd4391dSSanjay Patel       // to make the matched pair visible to the backend.
1046fd4391dSSanjay Patel       if (DivDominates)
1056fd4391dSSanjay Patel         RemInst->moveAfter(DivInst);
1066fd4391dSSanjay Patel       else
1076fd4391dSSanjay Patel         DivInst->moveAfter(RemInst);
1086fd4391dSSanjay Patel       NumHoisted++;
1096fd4391dSSanjay Patel     } else {
110*8e0cf076SRoman Lebedev       // The target does not have a single div/rem operation. Decompose the
111*8e0cf076SRoman Lebedev       // remainder calculation as:
1126fd4391dSSanjay Patel       // X % Y --> X - ((X / Y) * Y).
1136fd4391dSSanjay Patel       Value *X = RemInst->getOperand(0);
1146fd4391dSSanjay Patel       Value *Y = RemInst->getOperand(1);
1156fd4391dSSanjay Patel       Instruction *Mul = BinaryOperator::CreateMul(DivInst, Y);
1166fd4391dSSanjay Patel       Instruction *Sub = BinaryOperator::CreateSub(X, Mul);
1176fd4391dSSanjay Patel 
1186fd4391dSSanjay Patel       // If the remainder dominates, then hoist the division up to that block:
1196fd4391dSSanjay Patel       //
1206fd4391dSSanjay Patel       // bb1:
1216fd4391dSSanjay Patel       //   %rem = srem %x, %y
1226fd4391dSSanjay Patel       // bb2:
1236fd4391dSSanjay Patel       //   %div = sdiv %x, %y
1246fd4391dSSanjay Patel       // -->
1256fd4391dSSanjay Patel       // bb1:
1266fd4391dSSanjay Patel       //   %div = sdiv %x, %y
1276fd4391dSSanjay Patel       //   %mul = mul %div, %y
1286fd4391dSSanjay Patel       //   %rem = sub %x, %mul
1296fd4391dSSanjay Patel       //
1306fd4391dSSanjay Patel       // If the division dominates, it's already in the right place. The mul+sub
1316fd4391dSSanjay Patel       // will be in a different block because we don't assume that they are
1326fd4391dSSanjay Patel       // cheap to speculatively execute:
1336fd4391dSSanjay Patel       //
1346fd4391dSSanjay Patel       // bb1:
1356fd4391dSSanjay Patel       //   %div = sdiv %x, %y
1366fd4391dSSanjay Patel       // bb2:
1376fd4391dSSanjay Patel       //   %rem = srem %x, %y
1386fd4391dSSanjay Patel       // -->
1396fd4391dSSanjay Patel       // bb1:
1406fd4391dSSanjay Patel       //   %div = sdiv %x, %y
1416fd4391dSSanjay Patel       // bb2:
1426fd4391dSSanjay Patel       //   %mul = mul %div, %y
1436fd4391dSSanjay Patel       //   %rem = sub %x, %mul
1446fd4391dSSanjay Patel       //
1456fd4391dSSanjay Patel       // If the div and rem are in the same block, we do the same transform,
1466fd4391dSSanjay Patel       // but any code movement would be within the same block.
1476fd4391dSSanjay Patel 
1486fd4391dSSanjay Patel       if (!DivDominates)
1496fd4391dSSanjay Patel         DivInst->moveBefore(RemInst);
1506fd4391dSSanjay Patel       Mul->insertAfter(RemInst);
1516fd4391dSSanjay Patel       Sub->insertAfter(Mul);
1526fd4391dSSanjay Patel 
1536fd4391dSSanjay Patel       // Now kill the explicit remainder. We have replaced it with:
1546fd4391dSSanjay Patel       // (sub X, (mul (div X, Y), Y)
1556fd4391dSSanjay Patel       RemInst->replaceAllUsesWith(Sub);
1566fd4391dSSanjay Patel       RemInst->eraseFromParent();
1576fd4391dSSanjay Patel       NumDecomposed++;
1586fd4391dSSanjay Patel     }
1596fd4391dSSanjay Patel     Changed = true;
1606fd4391dSSanjay Patel   }
1616fd4391dSSanjay Patel 
1626fd4391dSSanjay Patel   return Changed;
1636fd4391dSSanjay Patel }
1646fd4391dSSanjay Patel 
1656fd4391dSSanjay Patel // Pass manager boilerplate below here.
1666fd4391dSSanjay Patel 
1676fd4391dSSanjay Patel namespace {
1686fd4391dSSanjay Patel struct DivRemPairsLegacyPass : public FunctionPass {
1696fd4391dSSanjay Patel   static char ID;
1706fd4391dSSanjay Patel   DivRemPairsLegacyPass() : FunctionPass(ID) {
1716fd4391dSSanjay Patel     initializeDivRemPairsLegacyPassPass(*PassRegistry::getPassRegistry());
1726fd4391dSSanjay Patel   }
1736fd4391dSSanjay Patel 
1746fd4391dSSanjay Patel   void getAnalysisUsage(AnalysisUsage &AU) const override {
1756fd4391dSSanjay Patel     AU.addRequired<DominatorTreeWrapperPass>();
1766fd4391dSSanjay Patel     AU.addRequired<TargetTransformInfoWrapperPass>();
1776fd4391dSSanjay Patel     AU.setPreservesCFG();
1786fd4391dSSanjay Patel     AU.addPreserved<DominatorTreeWrapperPass>();
1796fd4391dSSanjay Patel     AU.addPreserved<GlobalsAAWrapperPass>();
1806fd4391dSSanjay Patel     FunctionPass::getAnalysisUsage(AU);
1816fd4391dSSanjay Patel   }
1826fd4391dSSanjay Patel 
1836fd4391dSSanjay Patel   bool runOnFunction(Function &F) override {
1846fd4391dSSanjay Patel     if (skipFunction(F))
1856fd4391dSSanjay Patel       return false;
1866fd4391dSSanjay Patel     auto &TTI = getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
1876fd4391dSSanjay Patel     auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1886fd4391dSSanjay Patel     return optimizeDivRem(F, TTI, DT);
1896fd4391dSSanjay Patel   }
1906fd4391dSSanjay Patel };
1916fd4391dSSanjay Patel }
1926fd4391dSSanjay Patel 
1936fd4391dSSanjay Patel char DivRemPairsLegacyPass::ID = 0;
1946fd4391dSSanjay Patel INITIALIZE_PASS_BEGIN(DivRemPairsLegacyPass, "div-rem-pairs",
1956fd4391dSSanjay Patel                       "Hoist/decompose integer division and remainder", false,
1966fd4391dSSanjay Patel                       false)
1976fd4391dSSanjay Patel INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
1986fd4391dSSanjay Patel INITIALIZE_PASS_END(DivRemPairsLegacyPass, "div-rem-pairs",
1996fd4391dSSanjay Patel                     "Hoist/decompose integer division and remainder", false,
2006fd4391dSSanjay Patel                     false)
2016fd4391dSSanjay Patel FunctionPass *llvm::createDivRemPairsPass() {
2026fd4391dSSanjay Patel   return new DivRemPairsLegacyPass();
2036fd4391dSSanjay Patel }
2046fd4391dSSanjay Patel 
2056fd4391dSSanjay Patel PreservedAnalyses DivRemPairsPass::run(Function &F,
2066fd4391dSSanjay Patel                                        FunctionAnalysisManager &FAM) {
2076fd4391dSSanjay Patel   TargetTransformInfo &TTI = FAM.getResult<TargetIRAnalysis>(F);
2086fd4391dSSanjay Patel   DominatorTree &DT = FAM.getResult<DominatorTreeAnalysis>(F);
2096fd4391dSSanjay Patel   if (!optimizeDivRem(F, TTI, DT))
2106fd4391dSSanjay Patel     return PreservedAnalyses::all();
2116fd4391dSSanjay Patel   // TODO: This pass just hoists/replaces math ops - all analyses are preserved?
2126fd4391dSSanjay Patel   PreservedAnalyses PA;
2136fd4391dSSanjay Patel   PA.preserveSet<CFGAnalyses>();
2146fd4391dSSanjay Patel   PA.preserve<GlobalsAA>();
2156fd4391dSSanjay Patel   return PA;
2166fd4391dSSanjay Patel }
217