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