1a686c60cSRoman Lebedev //===- DivRemPairs.cpp - Hoist/[dr]ecompose division and remainder --------===// 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 // 9a686c60cSRoman Lebedev // This pass hoists and/or decomposes/recomposes 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" 2049f75132SJuneyoung Lee #include "llvm/Analysis/ValueTracking.h" 216fd4391dSSanjay Patel #include "llvm/IR/Dominators.h" 226fd4391dSSanjay Patel #include "llvm/IR/Function.h" 23a686c60cSRoman Lebedev #include "llvm/IR/PatternMatch.h" 2405da2fe5SReid Kleckner #include "llvm/InitializePasses.h" 256fd4391dSSanjay Patel #include "llvm/Pass.h" 26213d1d23SGeorge Burgess IV #include "llvm/Support/DebugCounter.h" 276fd4391dSSanjay Patel #include "llvm/Transforms/Scalar.h" 286fd4391dSSanjay Patel #include "llvm/Transforms/Utils/BypassSlowDivision.h" 295f616901SRoman Lebedev 306fd4391dSSanjay Patel using namespace llvm; 31a686c60cSRoman Lebedev using namespace llvm::PatternMatch; 326fd4391dSSanjay Patel 336fd4391dSSanjay Patel #define DEBUG_TYPE "div-rem-pairs" 346fd4391dSSanjay Patel STATISTIC(NumPairs, "Number of div/rem pairs"); 35a686c60cSRoman Lebedev STATISTIC(NumRecomposed, "Number of instructions recomposed"); 366fd4391dSSanjay Patel STATISTIC(NumHoisted, "Number of instructions hoisted"); 376fd4391dSSanjay Patel STATISTIC(NumDecomposed, "Number of instructions decomposed"); 38213d1d23SGeorge Burgess IV DEBUG_COUNTER(DRPCounter, "div-rem-pairs-transform", 39213d1d23SGeorge Burgess IV "Controls transformations in div-rem-pairs pass"); 406fd4391dSSanjay Patel 41a686c60cSRoman Lebedev namespace { 42a686c60cSRoman Lebedev struct ExpandedMatch { 43a686c60cSRoman Lebedev DivRemMapKey Key; 44a686c60cSRoman Lebedev Instruction *Value; 45a686c60cSRoman Lebedev }; 46a686c60cSRoman Lebedev } // namespace 47a686c60cSRoman Lebedev 48a686c60cSRoman Lebedev /// See if we can match: (which is the form we expand into) 49a686c60cSRoman Lebedev /// X - ((X ?/ Y) * Y) 50a686c60cSRoman Lebedev /// which is equivalent to: 51a686c60cSRoman Lebedev /// X ?% Y 52a686c60cSRoman Lebedev static llvm::Optional<ExpandedMatch> matchExpandedRem(Instruction &I) { 53a686c60cSRoman Lebedev Value *Dividend, *XroundedDownToMultipleOfY; 54a686c60cSRoman Lebedev if (!match(&I, m_Sub(m_Value(Dividend), m_Value(XroundedDownToMultipleOfY)))) 55a686c60cSRoman Lebedev return llvm::None; 56a686c60cSRoman Lebedev 57a686c60cSRoman Lebedev Value *Divisor; 58a686c60cSRoman Lebedev Instruction *Div; 59a686c60cSRoman Lebedev // Look for ((X / Y) * Y) 60a686c60cSRoman Lebedev if (!match( 61a686c60cSRoman Lebedev XroundedDownToMultipleOfY, 62a686c60cSRoman Lebedev m_c_Mul(m_CombineAnd(m_IDiv(m_Specific(Dividend), m_Value(Divisor)), 63a686c60cSRoman Lebedev m_Instruction(Div)), 64a686c60cSRoman Lebedev m_Deferred(Divisor)))) 65a686c60cSRoman Lebedev return llvm::None; 66a686c60cSRoman Lebedev 67a686c60cSRoman Lebedev ExpandedMatch M; 68a686c60cSRoman Lebedev M.Key.SignedOp = Div->getOpcode() == Instruction::SDiv; 69a686c60cSRoman Lebedev M.Key.Dividend = Dividend; 70a686c60cSRoman Lebedev M.Key.Divisor = Divisor; 71a686c60cSRoman Lebedev M.Value = &I; 72a686c60cSRoman Lebedev return M; 73a686c60cSRoman Lebedev } 74a686c60cSRoman Lebedev 75247a177cSBenjamin Kramer namespace { 765f616901SRoman Lebedev /// A thin wrapper to store two values that we matched as div-rem pair. 775f616901SRoman Lebedev /// We want this extra indirection to avoid dealing with RAUW'ing the map keys. 785f616901SRoman Lebedev struct DivRemPairWorklistEntry { 795f616901SRoman Lebedev /// The actual udiv/sdiv instruction. Source of truth. 805f616901SRoman Lebedev AssertingVH<Instruction> DivInst; 816fd4391dSSanjay Patel 825f616901SRoman Lebedev /// The instruction that we have matched as a remainder instruction. 835f616901SRoman Lebedev /// Should only be used as Value, don't introspect it. 845f616901SRoman Lebedev AssertingVH<Instruction> RemInst; 855f616901SRoman Lebedev 865f616901SRoman Lebedev DivRemPairWorklistEntry(Instruction *DivInst_, Instruction *RemInst_) 875f616901SRoman Lebedev : DivInst(DivInst_), RemInst(RemInst_) { 885f616901SRoman Lebedev assert((DivInst->getOpcode() == Instruction::UDiv || 895f616901SRoman Lebedev DivInst->getOpcode() == Instruction::SDiv) && 905f616901SRoman Lebedev "Not a division."); 915f616901SRoman Lebedev assert(DivInst->getType() == RemInst->getType() && "Types should match."); 925f616901SRoman Lebedev // We can't check anything else about remainder instruction, 935f616901SRoman Lebedev // it's not strictly required to be a urem/srem. 945f616901SRoman Lebedev } 955f616901SRoman Lebedev 965f616901SRoman Lebedev /// The type for this pair, identical for both the div and rem. 975f616901SRoman Lebedev Type *getType() const { return DivInst->getType(); } 985f616901SRoman Lebedev 995f616901SRoman Lebedev /// Is this pair signed or unsigned? 1005f616901SRoman Lebedev bool isSigned() const { return DivInst->getOpcode() == Instruction::SDiv; } 1015f616901SRoman Lebedev 1025f616901SRoman Lebedev /// In this pair, what are the divident and divisor? 1035f616901SRoman Lebedev Value *getDividend() const { return DivInst->getOperand(0); } 1045f616901SRoman Lebedev Value *getDivisor() const { return DivInst->getOperand(1); } 105a686c60cSRoman Lebedev 106a686c60cSRoman Lebedev bool isRemExpanded() const { 107a686c60cSRoman Lebedev switch (RemInst->getOpcode()) { 108a686c60cSRoman Lebedev case Instruction::SRem: 109a686c60cSRoman Lebedev case Instruction::URem: 110a686c60cSRoman Lebedev return false; // single 'rem' instruction - unexpanded form. 111a686c60cSRoman Lebedev default: 112a686c60cSRoman Lebedev return true; // anything else means we have remainder in expanded form. 113a686c60cSRoman Lebedev } 114a686c60cSRoman Lebedev } 1155f616901SRoman Lebedev }; 116247a177cSBenjamin Kramer } // namespace 1175f616901SRoman Lebedev using DivRemWorklistTy = SmallVector<DivRemPairWorklistEntry, 4>; 1185f616901SRoman Lebedev 1195f616901SRoman Lebedev /// Find matching pairs of integer div/rem ops (they have the same numerator, 1205f616901SRoman Lebedev /// denominator, and signedness). Place those pairs into a worklist for further 1215f616901SRoman Lebedev /// processing. This indirection is needed because we have to use TrackingVH<> 1225f616901SRoman Lebedev /// because we will be doing RAUW, and if one of the rem instructions we change 1235f616901SRoman Lebedev /// happens to be an input to another div/rem in the maps, we'd have problems. 1245f616901SRoman Lebedev static DivRemWorklistTy getWorklist(Function &F) { 1256fd4391dSSanjay Patel // Insert all divide and remainder instructions into maps keyed by their 1266fd4391dSSanjay Patel // operands and opcode (signed or unsigned). 1272af5f3c1SGeoff Berry DenseMap<DivRemMapKey, Instruction *> DivMap; 1282af5f3c1SGeoff Berry // Use a MapVector for RemMap so that instructions are moved/inserted in a 1292af5f3c1SGeoff Berry // deterministic order. 1308e0cf076SRoman Lebedev MapVector<DivRemMapKey, Instruction *> RemMap; 1316fd4391dSSanjay Patel for (auto &BB : F) { 1326fd4391dSSanjay Patel for (auto &I : BB) { 1336fd4391dSSanjay Patel if (I.getOpcode() == Instruction::SDiv) 1346fd4391dSSanjay Patel DivMap[DivRemMapKey(true, I.getOperand(0), I.getOperand(1))] = &I; 1356fd4391dSSanjay Patel else if (I.getOpcode() == Instruction::UDiv) 1366fd4391dSSanjay Patel DivMap[DivRemMapKey(false, I.getOperand(0), I.getOperand(1))] = &I; 1376fd4391dSSanjay Patel else if (I.getOpcode() == Instruction::SRem) 1388e0cf076SRoman Lebedev RemMap[DivRemMapKey(true, I.getOperand(0), I.getOperand(1))] = &I; 1396fd4391dSSanjay Patel else if (I.getOpcode() == Instruction::URem) 1408e0cf076SRoman Lebedev RemMap[DivRemMapKey(false, I.getOperand(0), I.getOperand(1))] = &I; 141a686c60cSRoman Lebedev else if (auto Match = matchExpandedRem(I)) 142a686c60cSRoman Lebedev RemMap[Match->Key] = Match->Value; 1436fd4391dSSanjay Patel } 1446fd4391dSSanjay Patel } 1456fd4391dSSanjay Patel 1465f616901SRoman Lebedev // We'll accumulate the matching pairs of div-rem instructions here. 1475f616901SRoman Lebedev DivRemWorklistTy Worklist; 1485f616901SRoman Lebedev 1496fd4391dSSanjay Patel // We can iterate over either map because we are only looking for matched 1506fd4391dSSanjay Patel // pairs. Choose remainders for efficiency because they are usually even more 1516fd4391dSSanjay Patel // rare than division. 1526fd4391dSSanjay Patel for (auto &RemPair : RemMap) { 1536fd4391dSSanjay Patel // Find the matching division instruction from the division map. 15482420b4eSFangrui Song auto It = DivMap.find(RemPair.first); 15582420b4eSFangrui Song if (It == DivMap.end()) 1566fd4391dSSanjay Patel continue; 1576fd4391dSSanjay Patel 1585f616901SRoman Lebedev // We have a matching pair of div/rem instructions. 1596fd4391dSSanjay Patel NumPairs++; 1608e0cf076SRoman Lebedev Instruction *RemInst = RemPair.second; 1615f616901SRoman Lebedev 1625f616901SRoman Lebedev // Place it in the worklist. 16382420b4eSFangrui Song Worklist.emplace_back(It->second, RemInst); 1645f616901SRoman Lebedev } 1655f616901SRoman Lebedev 1665f616901SRoman Lebedev return Worklist; 1675f616901SRoman Lebedev } 1685f616901SRoman Lebedev 1695f616901SRoman Lebedev /// Find matching pairs of integer div/rem ops (they have the same numerator, 1705f616901SRoman Lebedev /// denominator, and signedness). If they exist in different basic blocks, bring 1715f616901SRoman Lebedev /// them together by hoisting or replace the common division operation that is 1725f616901SRoman Lebedev /// implicit in the remainder: 1735f616901SRoman Lebedev /// X % Y <--> X - ((X / Y) * Y). 1745f616901SRoman Lebedev /// 1755f616901SRoman Lebedev /// We can largely ignore the normal safety and cost constraints on speculation 1765f616901SRoman Lebedev /// of these ops when we find a matching pair. This is because we are already 1775f616901SRoman Lebedev /// guaranteed that any exceptions and most cost are already incurred by the 1785f616901SRoman Lebedev /// first member of the pair. 1795f616901SRoman Lebedev /// 1805f616901SRoman Lebedev /// Note: This transform could be an oddball enhancement to EarlyCSE, GVN, or 1815f616901SRoman Lebedev /// SimplifyCFG, but it's split off on its own because it's different enough 1825f616901SRoman Lebedev /// that it doesn't quite match the stated objectives of those passes. 1835f616901SRoman Lebedev static bool optimizeDivRem(Function &F, const TargetTransformInfo &TTI, 1845f616901SRoman Lebedev const DominatorTree &DT) { 1855f616901SRoman Lebedev bool Changed = false; 1865f616901SRoman Lebedev 1875f616901SRoman Lebedev // Get the matching pairs of div-rem instructions. We want this extra 1885f616901SRoman Lebedev // indirection to avoid dealing with having to RAUW the keys of the maps. 1895f616901SRoman Lebedev DivRemWorklistTy Worklist = getWorklist(F); 1905f616901SRoman Lebedev 1915f616901SRoman Lebedev // Process each entry in the worklist. 1925f616901SRoman Lebedev for (DivRemPairWorklistEntry &E : Worklist) { 193a686c60cSRoman Lebedev if (!DebugCounter::shouldExecute(DRPCounter)) 194a686c60cSRoman Lebedev continue; 195a686c60cSRoman Lebedev 1965f616901SRoman Lebedev bool HasDivRemOp = TTI.hasDivRemOp(E.getType(), E.isSigned()); 1975f616901SRoman Lebedev 1985f616901SRoman Lebedev auto &DivInst = E.DivInst; 1995f616901SRoman Lebedev auto &RemInst = E.RemInst; 2006fd4391dSSanjay Patel 201a686c60cSRoman Lebedev const bool RemOriginallyWasInExpandedForm = E.isRemExpanded(); 2025e4e6b1fSRoman Lebedev (void)RemOriginallyWasInExpandedForm; // suppress unused variable warning 203a686c60cSRoman Lebedev 204a686c60cSRoman Lebedev if (HasDivRemOp && E.isRemExpanded()) { 205a686c60cSRoman Lebedev // The target supports div+rem but the rem is expanded. 206a686c60cSRoman Lebedev // We should recompose it first. 207a686c60cSRoman Lebedev Value *X = E.getDividend(); 208a686c60cSRoman Lebedev Value *Y = E.getDivisor(); 209a686c60cSRoman Lebedev Instruction *RealRem = E.isSigned() ? BinaryOperator::CreateSRem(X, Y) 210a686c60cSRoman Lebedev : BinaryOperator::CreateURem(X, Y); 211a686c60cSRoman Lebedev // Note that we place it right next to the original expanded instruction, 212a686c60cSRoman Lebedev // and letting further handling to move it if needed. 213a686c60cSRoman Lebedev RealRem->setName(RemInst->getName() + ".recomposed"); 214a686c60cSRoman Lebedev RealRem->insertAfter(RemInst); 215a686c60cSRoman Lebedev Instruction *OrigRemInst = RemInst; 216a686c60cSRoman Lebedev // Update AssertingVH<> with new instruction so it doesn't assert. 217a686c60cSRoman Lebedev RemInst = RealRem; 218a686c60cSRoman Lebedev // And replace the original instruction with the new one. 219a686c60cSRoman Lebedev OrigRemInst->replaceAllUsesWith(RealRem); 220a686c60cSRoman Lebedev OrigRemInst->eraseFromParent(); 221a686c60cSRoman Lebedev NumRecomposed++; 222a686c60cSRoman Lebedev // Note that we have left ((X / Y) * Y) around. 223a686c60cSRoman Lebedev // If it had other uses we could rewrite it as X - X % Y 2248405f6bcSserge-sans-paille Changed = true; 225a686c60cSRoman Lebedev } 226a686c60cSRoman Lebedev 227a686c60cSRoman Lebedev assert((!E.isRemExpanded() || !HasDivRemOp) && 228a686c60cSRoman Lebedev "*If* the target supports div-rem, then by now the RemInst *is* " 229a686c60cSRoman Lebedev "Instruction::[US]Rem."); 230a686c60cSRoman Lebedev 2316fd4391dSSanjay Patel // If the target supports div+rem and the instructions are in the same block 2326fd4391dSSanjay Patel // already, there's nothing to do. The backend should handle this. If the 2336fd4391dSSanjay Patel // target does not support div+rem, then we will decompose the rem. 2346fd4391dSSanjay Patel if (HasDivRemOp && RemInst->getParent() == DivInst->getParent()) 2356fd4391dSSanjay Patel continue; 2366fd4391dSSanjay Patel 2376fd4391dSSanjay Patel bool DivDominates = DT.dominates(DivInst, RemInst); 238a686c60cSRoman Lebedev if (!DivDominates && !DT.dominates(RemInst, DivInst)) { 239a686c60cSRoman Lebedev // We have matching div-rem pair, but they are in two different blocks, 240a686c60cSRoman Lebedev // neither of which dominates one another. 241*e38b7e89SCraig Topper 242*e38b7e89SCraig Topper BasicBlock *PredBB = nullptr; 243*e38b7e89SCraig Topper BasicBlock *DivBB = DivInst->getParent(); 244*e38b7e89SCraig Topper BasicBlock *RemBB = RemInst->getParent(); 245*e38b7e89SCraig Topper 246*e38b7e89SCraig Topper // It's only safe to hoist if every instruction before the Div/Rem in the 247*e38b7e89SCraig Topper // basic block is guaranteed to transfer execution. 248*e38b7e89SCraig Topper auto IsSafeToHoist = [](Instruction *DivOrRem, BasicBlock *ParentBB) { 249*e38b7e89SCraig Topper for (auto I = ParentBB->begin(), E = DivOrRem->getIterator(); I != E; 250*e38b7e89SCraig Topper ++I) 251*e38b7e89SCraig Topper if (!isGuaranteedToTransferExecutionToSuccessor(&*I)) 252*e38b7e89SCraig Topper return false; 253*e38b7e89SCraig Topper 254*e38b7e89SCraig Topper return true; 255*e38b7e89SCraig Topper }; 256*e38b7e89SCraig Topper 257*e38b7e89SCraig Topper // Look for something like this 258*e38b7e89SCraig Topper // PredBB 259*e38b7e89SCraig Topper // | \ 260*e38b7e89SCraig Topper // | Rem 261*e38b7e89SCraig Topper // | / 262*e38b7e89SCraig Topper // Div 263*e38b7e89SCraig Topper // 264*e38b7e89SCraig Topper // If the Rem block has a single predecessor and successor, and all paths 265*e38b7e89SCraig Topper // from PredBB go to either RemBB or DivBB, and execution of RemBB and 266*e38b7e89SCraig Topper // DivBB will always reach the Div/Rem, we can hoist Div to PredBB. If 267*e38b7e89SCraig Topper // we have a DivRem operation we can also hoist Rem. Otherwise we'll leave 268*e38b7e89SCraig Topper // Rem where it is and rewrite it to mul/sub. 269*e38b7e89SCraig Topper // FIXME: We could handle more hoisting cases. 270*e38b7e89SCraig Topper if (RemBB->getSingleSuccessor() == DivBB) 271*e38b7e89SCraig Topper PredBB = RemBB->getUniquePredecessor(); 272*e38b7e89SCraig Topper 273*e38b7e89SCraig Topper if (PredBB && IsSafeToHoist(RemInst, RemBB) && 274*e38b7e89SCraig Topper IsSafeToHoist(DivInst, DivBB) && 275*e38b7e89SCraig Topper llvm::all_of(successors(PredBB), [&](BasicBlock *BB) { 276*e38b7e89SCraig Topper return BB == DivBB || BB == RemBB; 277*e38b7e89SCraig Topper })) { 278*e38b7e89SCraig Topper DivDominates = true; 279*e38b7e89SCraig Topper DivInst->moveBefore(PredBB->getTerminator()); 280*e38b7e89SCraig Topper Changed = true; 281*e38b7e89SCraig Topper if (HasDivRemOp) { 282*e38b7e89SCraig Topper RemInst->moveBefore(PredBB->getTerminator()); 283*e38b7e89SCraig Topper continue; 284*e38b7e89SCraig Topper } 285*e38b7e89SCraig Topper } else 2866fd4391dSSanjay Patel continue; 287a686c60cSRoman Lebedev } 2886fd4391dSSanjay Patel 289a686c60cSRoman Lebedev // The target does not have a single div/rem operation, 290a686c60cSRoman Lebedev // and the rem is already in expanded form. Nothing to do. 291a686c60cSRoman Lebedev if (!HasDivRemOp && E.isRemExpanded()) 292213d1d23SGeorge Burgess IV continue; 293213d1d23SGeorge Burgess IV 2946fd4391dSSanjay Patel if (HasDivRemOp) { 2956fd4391dSSanjay Patel // The target has a single div/rem operation. Hoist the lower instruction 2966fd4391dSSanjay Patel // to make the matched pair visible to the backend. 2976fd4391dSSanjay Patel if (DivDominates) 2986fd4391dSSanjay Patel RemInst->moveAfter(DivInst); 2996fd4391dSSanjay Patel else 3006fd4391dSSanjay Patel DivInst->moveAfter(RemInst); 3016fd4391dSSanjay Patel NumHoisted++; 3026fd4391dSSanjay Patel } else { 303a686c60cSRoman Lebedev // The target does not have a single div/rem operation, 304a686c60cSRoman Lebedev // and the rem is *not* in a already-expanded form. 305a686c60cSRoman Lebedev // Decompose the remainder calculation as: 3066fd4391dSSanjay Patel // X % Y --> X - ((X / Y) * Y). 307a686c60cSRoman Lebedev 308a686c60cSRoman Lebedev assert(!RemOriginallyWasInExpandedForm && 309a686c60cSRoman Lebedev "We should not be expanding if the rem was in expanded form to " 310a686c60cSRoman Lebedev "begin with."); 311a686c60cSRoman Lebedev 3125f616901SRoman Lebedev Value *X = E.getDividend(); 3135f616901SRoman Lebedev Value *Y = E.getDivisor(); 3146fd4391dSSanjay Patel Instruction *Mul = BinaryOperator::CreateMul(DivInst, Y); 3156fd4391dSSanjay Patel Instruction *Sub = BinaryOperator::CreateSub(X, Mul); 3166fd4391dSSanjay Patel 3176fd4391dSSanjay Patel // If the remainder dominates, then hoist the division up to that block: 3186fd4391dSSanjay Patel // 3196fd4391dSSanjay Patel // bb1: 3206fd4391dSSanjay Patel // %rem = srem %x, %y 3216fd4391dSSanjay Patel // bb2: 3226fd4391dSSanjay Patel // %div = sdiv %x, %y 3236fd4391dSSanjay Patel // --> 3246fd4391dSSanjay Patel // bb1: 3256fd4391dSSanjay Patel // %div = sdiv %x, %y 3266fd4391dSSanjay Patel // %mul = mul %div, %y 3276fd4391dSSanjay Patel // %rem = sub %x, %mul 3286fd4391dSSanjay Patel // 3296fd4391dSSanjay Patel // If the division dominates, it's already in the right place. The mul+sub 3306fd4391dSSanjay Patel // will be in a different block because we don't assume that they are 3316fd4391dSSanjay Patel // cheap to speculatively execute: 3326fd4391dSSanjay Patel // 3336fd4391dSSanjay Patel // bb1: 3346fd4391dSSanjay Patel // %div = sdiv %x, %y 3356fd4391dSSanjay Patel // bb2: 3366fd4391dSSanjay Patel // %rem = srem %x, %y 3376fd4391dSSanjay Patel // --> 3386fd4391dSSanjay Patel // bb1: 3396fd4391dSSanjay Patel // %div = sdiv %x, %y 3406fd4391dSSanjay Patel // bb2: 3416fd4391dSSanjay Patel // %mul = mul %div, %y 3426fd4391dSSanjay Patel // %rem = sub %x, %mul 3436fd4391dSSanjay Patel // 3446fd4391dSSanjay Patel // If the div and rem are in the same block, we do the same transform, 3456fd4391dSSanjay Patel // but any code movement would be within the same block. 3466fd4391dSSanjay Patel 3476fd4391dSSanjay Patel if (!DivDominates) 3486fd4391dSSanjay Patel DivInst->moveBefore(RemInst); 3496fd4391dSSanjay Patel Mul->insertAfter(RemInst); 3506fd4391dSSanjay Patel Sub->insertAfter(Mul); 3516fd4391dSSanjay Patel 35249f75132SJuneyoung Lee // If X can be undef, X should be frozen first. 35349f75132SJuneyoung Lee // For example, let's assume that Y = 1 & X = undef: 35449f75132SJuneyoung Lee // %div = sdiv undef, 1 // %div = undef 35549f75132SJuneyoung Lee // %rem = srem undef, 1 // %rem = 0 35649f75132SJuneyoung Lee // => 35749f75132SJuneyoung Lee // %div = sdiv undef, 1 // %div = undef 35849f75132SJuneyoung Lee // %mul = mul %div, 1 // %mul = undef 35949f75132SJuneyoung Lee // %rem = sub %x, %mul // %rem = undef - undef = undef 36049f75132SJuneyoung Lee // If X is not frozen, %rem becomes undef after transformation. 36149f75132SJuneyoung Lee // TODO: We need a undef-specific checking function in ValueTracking 3629b3c2a72SJuneyoung Lee if (!isGuaranteedNotToBeUndefOrPoison(X, nullptr, DivInst, &DT)) { 36349f75132SJuneyoung Lee auto *FrX = new FreezeInst(X, X->getName() + ".frozen", DivInst); 36449f75132SJuneyoung Lee DivInst->setOperand(0, FrX); 36549f75132SJuneyoung Lee Sub->setOperand(0, FrX); 36649f75132SJuneyoung Lee } 36749f75132SJuneyoung Lee // Same for Y. If X = 1 and Y = (undef | 1), %rem in src is either 1 or 0, 36849f75132SJuneyoung Lee // but %rem in tgt can be one of many integer values. 3699b3c2a72SJuneyoung Lee if (!isGuaranteedNotToBeUndefOrPoison(Y, nullptr, DivInst, &DT)) { 37049f75132SJuneyoung Lee auto *FrY = new FreezeInst(Y, Y->getName() + ".frozen", DivInst); 37149f75132SJuneyoung Lee DivInst->setOperand(1, FrY); 37249f75132SJuneyoung Lee Mul->setOperand(1, FrY); 37349f75132SJuneyoung Lee } 37449f75132SJuneyoung Lee 3756fd4391dSSanjay Patel // Now kill the explicit remainder. We have replaced it with: 3766fd4391dSSanjay Patel // (sub X, (mul (div X, Y), Y) 3775f616901SRoman Lebedev Sub->setName(RemInst->getName() + ".decomposed"); 3785f616901SRoman Lebedev Instruction *OrigRemInst = RemInst; 3795f616901SRoman Lebedev // Update AssertingVH<> with new instruction so it doesn't assert. 3805f616901SRoman Lebedev RemInst = Sub; 3815f616901SRoman Lebedev // And replace the original instruction with the new one. 3825f616901SRoman Lebedev OrigRemInst->replaceAllUsesWith(Sub); 3835f616901SRoman Lebedev OrigRemInst->eraseFromParent(); 3846fd4391dSSanjay Patel NumDecomposed++; 3856fd4391dSSanjay Patel } 3866fd4391dSSanjay Patel Changed = true; 3876fd4391dSSanjay Patel } 3886fd4391dSSanjay Patel 3896fd4391dSSanjay Patel return Changed; 3906fd4391dSSanjay Patel } 3916fd4391dSSanjay Patel 3926fd4391dSSanjay Patel // Pass manager boilerplate below here. 3936fd4391dSSanjay Patel 3946fd4391dSSanjay Patel namespace { 3956fd4391dSSanjay Patel struct DivRemPairsLegacyPass : public FunctionPass { 3966fd4391dSSanjay Patel static char ID; 3976fd4391dSSanjay Patel DivRemPairsLegacyPass() : FunctionPass(ID) { 3986fd4391dSSanjay Patel initializeDivRemPairsLegacyPassPass(*PassRegistry::getPassRegistry()); 3996fd4391dSSanjay Patel } 4006fd4391dSSanjay Patel 4016fd4391dSSanjay Patel void getAnalysisUsage(AnalysisUsage &AU) const override { 4026fd4391dSSanjay Patel AU.addRequired<DominatorTreeWrapperPass>(); 4036fd4391dSSanjay Patel AU.addRequired<TargetTransformInfoWrapperPass>(); 4046fd4391dSSanjay Patel AU.setPreservesCFG(); 4056fd4391dSSanjay Patel AU.addPreserved<DominatorTreeWrapperPass>(); 4066fd4391dSSanjay Patel AU.addPreserved<GlobalsAAWrapperPass>(); 4076fd4391dSSanjay Patel FunctionPass::getAnalysisUsage(AU); 4086fd4391dSSanjay Patel } 4096fd4391dSSanjay Patel 4106fd4391dSSanjay Patel bool runOnFunction(Function &F) override { 4116fd4391dSSanjay Patel if (skipFunction(F)) 4126fd4391dSSanjay Patel return false; 4136fd4391dSSanjay Patel auto &TTI = getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F); 4146fd4391dSSanjay Patel auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree(); 4156fd4391dSSanjay Patel return optimizeDivRem(F, TTI, DT); 4166fd4391dSSanjay Patel } 4176fd4391dSSanjay Patel }; 4185f616901SRoman Lebedev } // namespace 4196fd4391dSSanjay Patel 4206fd4391dSSanjay Patel char DivRemPairsLegacyPass::ID = 0; 4216fd4391dSSanjay Patel INITIALIZE_PASS_BEGIN(DivRemPairsLegacyPass, "div-rem-pairs", 4226fd4391dSSanjay Patel "Hoist/decompose integer division and remainder", false, 4236fd4391dSSanjay Patel false) 4246fd4391dSSanjay Patel INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) 4256fd4391dSSanjay Patel INITIALIZE_PASS_END(DivRemPairsLegacyPass, "div-rem-pairs", 4266fd4391dSSanjay Patel "Hoist/decompose integer division and remainder", false, 4276fd4391dSSanjay Patel false) 4286fd4391dSSanjay Patel FunctionPass *llvm::createDivRemPairsPass() { 4296fd4391dSSanjay Patel return new DivRemPairsLegacyPass(); 4306fd4391dSSanjay Patel } 4316fd4391dSSanjay Patel 4326fd4391dSSanjay Patel PreservedAnalyses DivRemPairsPass::run(Function &F, 4336fd4391dSSanjay Patel FunctionAnalysisManager &FAM) { 4346fd4391dSSanjay Patel TargetTransformInfo &TTI = FAM.getResult<TargetIRAnalysis>(F); 4356fd4391dSSanjay Patel DominatorTree &DT = FAM.getResult<DominatorTreeAnalysis>(F); 4366fd4391dSSanjay Patel if (!optimizeDivRem(F, TTI, DT)) 4376fd4391dSSanjay Patel return PreservedAnalyses::all(); 4386fd4391dSSanjay Patel // TODO: This pass just hoists/replaces math ops - all analyses are preserved? 4396fd4391dSSanjay Patel PreservedAnalyses PA; 4406fd4391dSSanjay Patel PA.preserveSet<CFGAnalyses>(); 4416fd4391dSSanjay Patel return PA; 4426fd4391dSSanjay Patel } 443