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