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
matchExpandedRem(Instruction & I)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
DivRemPairWorklistEntry__anonb20a39290211::DivRemPairWorklistEntry865f616901SRoman 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.
getType__anonb20a39290211::DivRemPairWorklistEntry975f616901SRoman Lebedev Type *getType() const { return DivInst->getType(); }
985f616901SRoman Lebedev
995f616901SRoman Lebedev /// Is this pair signed or unsigned?
isSigned__anonb20a39290211::DivRemPairWorklistEntry1005f616901SRoman Lebedev bool isSigned() const { return DivInst->getOpcode() == Instruction::SDiv; }
1015f616901SRoman Lebedev
1025f616901SRoman Lebedev /// In this pair, what are the divident and divisor?
getDividend__anonb20a39290211::DivRemPairWorklistEntry1035f616901SRoman Lebedev Value *getDividend() const { return DivInst->getOperand(0); }
getDivisor__anonb20a39290211::DivRemPairWorklistEntry1045f616901SRoman Lebedev Value *getDivisor() const { return DivInst->getOperand(1); }
105a686c60cSRoman Lebedev
isRemExpanded__anonb20a39290211::DivRemPairWorklistEntry106a686c60cSRoman 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.
getWorklist(Function & F)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.
optimizeDivRem(Function & F,const TargetTransformInfo & TTI,const DominatorTree & DT)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.
241e38b7e89SCraig Topper
242e38b7e89SCraig Topper BasicBlock *PredBB = nullptr;
243e38b7e89SCraig Topper BasicBlock *DivBB = DivInst->getParent();
244e38b7e89SCraig Topper BasicBlock *RemBB = RemInst->getParent();
245e38b7e89SCraig Topper
246e38b7e89SCraig Topper // It's only safe to hoist if every instruction before the Div/Rem in the
247e38b7e89SCraig Topper // basic block is guaranteed to transfer execution.
248e38b7e89SCraig Topper auto IsSafeToHoist = [](Instruction *DivOrRem, BasicBlock *ParentBB) {
249e38b7e89SCraig Topper for (auto I = ParentBB->begin(), E = DivOrRem->getIterator(); I != E;
250e38b7e89SCraig Topper ++I)
251e38b7e89SCraig Topper if (!isGuaranteedToTransferExecutionToSuccessor(&*I))
252e38b7e89SCraig Topper return false;
253e38b7e89SCraig Topper
254e38b7e89SCraig Topper return true;
255e38b7e89SCraig Topper };
256e38b7e89SCraig Topper
257e38b7e89SCraig Topper // Look for something like this
258e38b7e89SCraig Topper // PredBB
259e38b7e89SCraig Topper // | \
260e38b7e89SCraig Topper // | Rem
261e38b7e89SCraig Topper // | /
262e38b7e89SCraig Topper // Div
263e38b7e89SCraig Topper //
264e38b7e89SCraig Topper // If the Rem block has a single predecessor and successor, and all paths
265e38b7e89SCraig Topper // from PredBB go to either RemBB or DivBB, and execution of RemBB and
266e38b7e89SCraig Topper // DivBB will always reach the Div/Rem, we can hoist Div to PredBB. If
267e38b7e89SCraig Topper // we have a DivRem operation we can also hoist Rem. Otherwise we'll leave
268e38b7e89SCraig Topper // Rem where it is and rewrite it to mul/sub.
269e38b7e89SCraig Topper // FIXME: We could handle more hoisting cases.
270e38b7e89SCraig Topper if (RemBB->getSingleSuccessor() == DivBB)
271e38b7e89SCraig Topper PredBB = RemBB->getUniquePredecessor();
272e38b7e89SCraig Topper
273e38b7e89SCraig Topper if (PredBB && IsSafeToHoist(RemInst, RemBB) &&
274e38b7e89SCraig Topper IsSafeToHoist(DivInst, DivBB) &&
275*5b83261cSSanjay Patel all_of(successors(PredBB),
276*5b83261cSSanjay Patel [&](BasicBlock *BB) { return BB == DivBB || BB == RemBB; }) &&
277*5b83261cSSanjay Patel all_of(predecessors(DivBB),
278*5b83261cSSanjay Patel [&](BasicBlock *BB) { return BB == RemBB || BB == PredBB; })) {
279e38b7e89SCraig Topper DivDominates = true;
280e38b7e89SCraig Topper DivInst->moveBefore(PredBB->getTerminator());
281e38b7e89SCraig Topper Changed = true;
282e38b7e89SCraig Topper if (HasDivRemOp) {
283e38b7e89SCraig Topper RemInst->moveBefore(PredBB->getTerminator());
284e38b7e89SCraig Topper continue;
285e38b7e89SCraig Topper }
286e38b7e89SCraig Topper } else
2876fd4391dSSanjay Patel continue;
288a686c60cSRoman Lebedev }
2896fd4391dSSanjay Patel
290a686c60cSRoman Lebedev // The target does not have a single div/rem operation,
291a686c60cSRoman Lebedev // and the rem is already in expanded form. Nothing to do.
292a686c60cSRoman Lebedev if (!HasDivRemOp && E.isRemExpanded())
293213d1d23SGeorge Burgess IV continue;
294213d1d23SGeorge Burgess IV
2956fd4391dSSanjay Patel if (HasDivRemOp) {
2966fd4391dSSanjay Patel // The target has a single div/rem operation. Hoist the lower instruction
2976fd4391dSSanjay Patel // to make the matched pair visible to the backend.
2986fd4391dSSanjay Patel if (DivDominates)
2996fd4391dSSanjay Patel RemInst->moveAfter(DivInst);
3006fd4391dSSanjay Patel else
3016fd4391dSSanjay Patel DivInst->moveAfter(RemInst);
3026fd4391dSSanjay Patel NumHoisted++;
3036fd4391dSSanjay Patel } else {
304a686c60cSRoman Lebedev // The target does not have a single div/rem operation,
305a686c60cSRoman Lebedev // and the rem is *not* in a already-expanded form.
306a686c60cSRoman Lebedev // Decompose the remainder calculation as:
3076fd4391dSSanjay Patel // X % Y --> X - ((X / Y) * Y).
308a686c60cSRoman Lebedev
309a686c60cSRoman Lebedev assert(!RemOriginallyWasInExpandedForm &&
310a686c60cSRoman Lebedev "We should not be expanding if the rem was in expanded form to "
311a686c60cSRoman Lebedev "begin with.");
312a686c60cSRoman Lebedev
3135f616901SRoman Lebedev Value *X = E.getDividend();
3145f616901SRoman Lebedev Value *Y = E.getDivisor();
3156fd4391dSSanjay Patel Instruction *Mul = BinaryOperator::CreateMul(DivInst, Y);
3166fd4391dSSanjay Patel Instruction *Sub = BinaryOperator::CreateSub(X, Mul);
3176fd4391dSSanjay Patel
3186fd4391dSSanjay Patel // If the remainder dominates, then hoist the division up to that block:
3196fd4391dSSanjay Patel //
3206fd4391dSSanjay Patel // bb1:
3216fd4391dSSanjay Patel // %rem = srem %x, %y
3226fd4391dSSanjay Patel // bb2:
3236fd4391dSSanjay Patel // %div = sdiv %x, %y
3246fd4391dSSanjay Patel // -->
3256fd4391dSSanjay Patel // bb1:
3266fd4391dSSanjay Patel // %div = sdiv %x, %y
3276fd4391dSSanjay Patel // %mul = mul %div, %y
3286fd4391dSSanjay Patel // %rem = sub %x, %mul
3296fd4391dSSanjay Patel //
3306fd4391dSSanjay Patel // If the division dominates, it's already in the right place. The mul+sub
3316fd4391dSSanjay Patel // will be in a different block because we don't assume that they are
3326fd4391dSSanjay Patel // cheap to speculatively execute:
3336fd4391dSSanjay Patel //
3346fd4391dSSanjay Patel // bb1:
3356fd4391dSSanjay Patel // %div = sdiv %x, %y
3366fd4391dSSanjay Patel // bb2:
3376fd4391dSSanjay Patel // %rem = srem %x, %y
3386fd4391dSSanjay Patel // -->
3396fd4391dSSanjay Patel // bb1:
3406fd4391dSSanjay Patel // %div = sdiv %x, %y
3416fd4391dSSanjay Patel // bb2:
3426fd4391dSSanjay Patel // %mul = mul %div, %y
3436fd4391dSSanjay Patel // %rem = sub %x, %mul
3446fd4391dSSanjay Patel //
3456fd4391dSSanjay Patel // If the div and rem are in the same block, we do the same transform,
3466fd4391dSSanjay Patel // but any code movement would be within the same block.
3476fd4391dSSanjay Patel
3486fd4391dSSanjay Patel if (!DivDominates)
3496fd4391dSSanjay Patel DivInst->moveBefore(RemInst);
3506fd4391dSSanjay Patel Mul->insertAfter(RemInst);
3516fd4391dSSanjay Patel Sub->insertAfter(Mul);
3526fd4391dSSanjay Patel
35349f75132SJuneyoung Lee // If X can be undef, X should be frozen first.
35449f75132SJuneyoung Lee // For example, let's assume that Y = 1 & X = undef:
35549f75132SJuneyoung Lee // %div = sdiv undef, 1 // %div = undef
35649f75132SJuneyoung Lee // %rem = srem undef, 1 // %rem = 0
35749f75132SJuneyoung Lee // =>
35849f75132SJuneyoung Lee // %div = sdiv undef, 1 // %div = undef
35949f75132SJuneyoung Lee // %mul = mul %div, 1 // %mul = undef
36049f75132SJuneyoung Lee // %rem = sub %x, %mul // %rem = undef - undef = undef
36149f75132SJuneyoung Lee // If X is not frozen, %rem becomes undef after transformation.
36249f75132SJuneyoung Lee // TODO: We need a undef-specific checking function in ValueTracking
3639b3c2a72SJuneyoung Lee if (!isGuaranteedNotToBeUndefOrPoison(X, nullptr, DivInst, &DT)) {
36449f75132SJuneyoung Lee auto *FrX = new FreezeInst(X, X->getName() + ".frozen", DivInst);
36549f75132SJuneyoung Lee DivInst->setOperand(0, FrX);
36649f75132SJuneyoung Lee Sub->setOperand(0, FrX);
36749f75132SJuneyoung Lee }
36849f75132SJuneyoung Lee // Same for Y. If X = 1 and Y = (undef | 1), %rem in src is either 1 or 0,
36949f75132SJuneyoung Lee // but %rem in tgt can be one of many integer values.
3709b3c2a72SJuneyoung Lee if (!isGuaranteedNotToBeUndefOrPoison(Y, nullptr, DivInst, &DT)) {
37149f75132SJuneyoung Lee auto *FrY = new FreezeInst(Y, Y->getName() + ".frozen", DivInst);
37249f75132SJuneyoung Lee DivInst->setOperand(1, FrY);
37349f75132SJuneyoung Lee Mul->setOperand(1, FrY);
37449f75132SJuneyoung Lee }
37549f75132SJuneyoung Lee
3766fd4391dSSanjay Patel // Now kill the explicit remainder. We have replaced it with:
3776fd4391dSSanjay Patel // (sub X, (mul (div X, Y), Y)
3785f616901SRoman Lebedev Sub->setName(RemInst->getName() + ".decomposed");
3795f616901SRoman Lebedev Instruction *OrigRemInst = RemInst;
3805f616901SRoman Lebedev // Update AssertingVH<> with new instruction so it doesn't assert.
3815f616901SRoman Lebedev RemInst = Sub;
3825f616901SRoman Lebedev // And replace the original instruction with the new one.
3835f616901SRoman Lebedev OrigRemInst->replaceAllUsesWith(Sub);
3845f616901SRoman Lebedev OrigRemInst->eraseFromParent();
3856fd4391dSSanjay Patel NumDecomposed++;
3866fd4391dSSanjay Patel }
3876fd4391dSSanjay Patel Changed = true;
3886fd4391dSSanjay Patel }
3896fd4391dSSanjay Patel
3906fd4391dSSanjay Patel return Changed;
3916fd4391dSSanjay Patel }
3926fd4391dSSanjay Patel
3936fd4391dSSanjay Patel // Pass manager boilerplate below here.
3946fd4391dSSanjay Patel
3956fd4391dSSanjay Patel namespace {
3966fd4391dSSanjay Patel struct DivRemPairsLegacyPass : public FunctionPass {
3976fd4391dSSanjay Patel static char ID;
DivRemPairsLegacyPass__anonb20a39290611::DivRemPairsLegacyPass3986fd4391dSSanjay Patel DivRemPairsLegacyPass() : FunctionPass(ID) {
3996fd4391dSSanjay Patel initializeDivRemPairsLegacyPassPass(*PassRegistry::getPassRegistry());
4006fd4391dSSanjay Patel }
4016fd4391dSSanjay Patel
getAnalysisUsage__anonb20a39290611::DivRemPairsLegacyPass4026fd4391dSSanjay Patel void getAnalysisUsage(AnalysisUsage &AU) const override {
4036fd4391dSSanjay Patel AU.addRequired<DominatorTreeWrapperPass>();
4046fd4391dSSanjay Patel AU.addRequired<TargetTransformInfoWrapperPass>();
4056fd4391dSSanjay Patel AU.setPreservesCFG();
4066fd4391dSSanjay Patel AU.addPreserved<DominatorTreeWrapperPass>();
4076fd4391dSSanjay Patel AU.addPreserved<GlobalsAAWrapperPass>();
4086fd4391dSSanjay Patel FunctionPass::getAnalysisUsage(AU);
4096fd4391dSSanjay Patel }
4106fd4391dSSanjay Patel
runOnFunction__anonb20a39290611::DivRemPairsLegacyPass4116fd4391dSSanjay Patel bool runOnFunction(Function &F) override {
4126fd4391dSSanjay Patel if (skipFunction(F))
4136fd4391dSSanjay Patel return false;
4146fd4391dSSanjay Patel auto &TTI = getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
4156fd4391dSSanjay Patel auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
4166fd4391dSSanjay Patel return optimizeDivRem(F, TTI, DT);
4176fd4391dSSanjay Patel }
4186fd4391dSSanjay Patel };
4195f616901SRoman Lebedev } // namespace
4206fd4391dSSanjay Patel
4216fd4391dSSanjay Patel char DivRemPairsLegacyPass::ID = 0;
4226fd4391dSSanjay Patel INITIALIZE_PASS_BEGIN(DivRemPairsLegacyPass, "div-rem-pairs",
4236fd4391dSSanjay Patel "Hoist/decompose integer division and remainder", false,
4246fd4391dSSanjay Patel false)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)4256fd4391dSSanjay Patel INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
4266fd4391dSSanjay Patel INITIALIZE_PASS_END(DivRemPairsLegacyPass, "div-rem-pairs",
4276fd4391dSSanjay Patel "Hoist/decompose integer division and remainder", false,
4286fd4391dSSanjay Patel false)
4296fd4391dSSanjay Patel FunctionPass *llvm::createDivRemPairsPass() {
4306fd4391dSSanjay Patel return new DivRemPairsLegacyPass();
4316fd4391dSSanjay Patel }
4326fd4391dSSanjay Patel
run(Function & F,FunctionAnalysisManager & FAM)4336fd4391dSSanjay Patel PreservedAnalyses DivRemPairsPass::run(Function &F,
4346fd4391dSSanjay Patel FunctionAnalysisManager &FAM) {
4356fd4391dSSanjay Patel TargetTransformInfo &TTI = FAM.getResult<TargetIRAnalysis>(F);
4366fd4391dSSanjay Patel DominatorTree &DT = FAM.getResult<DominatorTreeAnalysis>(F);
4376fd4391dSSanjay Patel if (!optimizeDivRem(F, TTI, DT))
4386fd4391dSSanjay Patel return PreservedAnalyses::all();
4396fd4391dSSanjay Patel // TODO: This pass just hoists/replaces math ops - all analyses are preserved?
4406fd4391dSSanjay Patel PreservedAnalyses PA;
4416fd4391dSSanjay Patel PA.preserveSet<CFGAnalyses>();
4426fd4391dSSanjay Patel return PA;
4436fd4391dSSanjay Patel }
444