18bcb0991SDimitry Andric //===- DivRemPairs.cpp - Hoist/[dr]ecompose division and remainder --------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
98bcb0991SDimitry Andric // This pass hoists and/or decomposes/recomposes integer division and remainder
100b57cec5SDimitry Andric // instructions to enable CFG improvements and better codegen.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/DivRemPairs.h"
150b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
160b57cec5SDimitry Andric #include "llvm/ADT/MapVector.h"
170b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
180b57cec5SDimitry Andric #include "llvm/Analysis/GlobalsModRef.h"
190b57cec5SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h"
205ffd83dbSDimitry Andric #include "llvm/Analysis/ValueTracking.h"
210b57cec5SDimitry Andric #include "llvm/IR/Dominators.h"
220b57cec5SDimitry Andric #include "llvm/IR/Function.h"
238bcb0991SDimitry Andric #include "llvm/IR/PatternMatch.h"
240b57cec5SDimitry Andric #include "llvm/Support/DebugCounter.h"
250b57cec5SDimitry Andric #include "llvm/Transforms/Utils/BypassSlowDivision.h"
26bdd1243dSDimitry Andric #include <optional>
270b57cec5SDimitry Andric
280b57cec5SDimitry Andric using namespace llvm;
298bcb0991SDimitry Andric using namespace llvm::PatternMatch;
300b57cec5SDimitry Andric
310b57cec5SDimitry Andric #define DEBUG_TYPE "div-rem-pairs"
320b57cec5SDimitry Andric STATISTIC(NumPairs, "Number of div/rem pairs");
338bcb0991SDimitry Andric STATISTIC(NumRecomposed, "Number of instructions recomposed");
340b57cec5SDimitry Andric STATISTIC(NumHoisted, "Number of instructions hoisted");
350b57cec5SDimitry Andric STATISTIC(NumDecomposed, "Number of instructions decomposed");
360b57cec5SDimitry Andric DEBUG_COUNTER(DRPCounter, "div-rem-pairs-transform",
370b57cec5SDimitry Andric "Controls transformations in div-rem-pairs pass");
380b57cec5SDimitry Andric
398bcb0991SDimitry Andric namespace {
408bcb0991SDimitry Andric struct ExpandedMatch {
418bcb0991SDimitry Andric DivRemMapKey Key;
428bcb0991SDimitry Andric Instruction *Value;
438bcb0991SDimitry Andric };
448bcb0991SDimitry Andric } // namespace
458bcb0991SDimitry Andric
468bcb0991SDimitry Andric /// See if we can match: (which is the form we expand into)
478bcb0991SDimitry Andric /// X - ((X ?/ Y) * Y)
488bcb0991SDimitry Andric /// which is equivalent to:
498bcb0991SDimitry Andric /// X ?% Y
matchExpandedRem(Instruction & I)50bdd1243dSDimitry Andric static std::optional<ExpandedMatch> matchExpandedRem(Instruction &I) {
518bcb0991SDimitry Andric Value *Dividend, *XroundedDownToMultipleOfY;
528bcb0991SDimitry Andric if (!match(&I, m_Sub(m_Value(Dividend), m_Value(XroundedDownToMultipleOfY))))
53bdd1243dSDimitry Andric return std::nullopt;
548bcb0991SDimitry Andric
558bcb0991SDimitry Andric Value *Divisor;
568bcb0991SDimitry Andric Instruction *Div;
578bcb0991SDimitry Andric // Look for ((X / Y) * Y)
588bcb0991SDimitry Andric if (!match(
598bcb0991SDimitry Andric XroundedDownToMultipleOfY,
608bcb0991SDimitry Andric m_c_Mul(m_CombineAnd(m_IDiv(m_Specific(Dividend), m_Value(Divisor)),
618bcb0991SDimitry Andric m_Instruction(Div)),
628bcb0991SDimitry Andric m_Deferred(Divisor))))
63bdd1243dSDimitry Andric return std::nullopt;
648bcb0991SDimitry Andric
658bcb0991SDimitry Andric ExpandedMatch M;
668bcb0991SDimitry Andric M.Key.SignedOp = Div->getOpcode() == Instruction::SDiv;
678bcb0991SDimitry Andric M.Key.Dividend = Dividend;
688bcb0991SDimitry Andric M.Key.Divisor = Divisor;
698bcb0991SDimitry Andric M.Value = &I;
708bcb0991SDimitry Andric return M;
718bcb0991SDimitry Andric }
728bcb0991SDimitry Andric
735ffd83dbSDimitry Andric namespace {
740b57cec5SDimitry Andric /// A thin wrapper to store two values that we matched as div-rem pair.
750b57cec5SDimitry Andric /// We want this extra indirection to avoid dealing with RAUW'ing the map keys.
760b57cec5SDimitry Andric struct DivRemPairWorklistEntry {
770b57cec5SDimitry Andric /// The actual udiv/sdiv instruction. Source of truth.
780b57cec5SDimitry Andric AssertingVH<Instruction> DivInst;
790b57cec5SDimitry Andric
800b57cec5SDimitry Andric /// The instruction that we have matched as a remainder instruction.
810b57cec5SDimitry Andric /// Should only be used as Value, don't introspect it.
820b57cec5SDimitry Andric AssertingVH<Instruction> RemInst;
830b57cec5SDimitry Andric
DivRemPairWorklistEntry__anon5efc93f90211::DivRemPairWorklistEntry840b57cec5SDimitry Andric DivRemPairWorklistEntry(Instruction *DivInst_, Instruction *RemInst_)
850b57cec5SDimitry Andric : DivInst(DivInst_), RemInst(RemInst_) {
860b57cec5SDimitry Andric assert((DivInst->getOpcode() == Instruction::UDiv ||
870b57cec5SDimitry Andric DivInst->getOpcode() == Instruction::SDiv) &&
880b57cec5SDimitry Andric "Not a division.");
890b57cec5SDimitry Andric assert(DivInst->getType() == RemInst->getType() && "Types should match.");
900b57cec5SDimitry Andric // We can't check anything else about remainder instruction,
910b57cec5SDimitry Andric // it's not strictly required to be a urem/srem.
920b57cec5SDimitry Andric }
930b57cec5SDimitry Andric
940b57cec5SDimitry Andric /// The type for this pair, identical for both the div and rem.
getType__anon5efc93f90211::DivRemPairWorklistEntry950b57cec5SDimitry Andric Type *getType() const { return DivInst->getType(); }
960b57cec5SDimitry Andric
970b57cec5SDimitry Andric /// Is this pair signed or unsigned?
isSigned__anon5efc93f90211::DivRemPairWorklistEntry980b57cec5SDimitry Andric bool isSigned() const { return DivInst->getOpcode() == Instruction::SDiv; }
990b57cec5SDimitry Andric
1000b57cec5SDimitry Andric /// In this pair, what are the divident and divisor?
getDividend__anon5efc93f90211::DivRemPairWorklistEntry1010b57cec5SDimitry Andric Value *getDividend() const { return DivInst->getOperand(0); }
getDivisor__anon5efc93f90211::DivRemPairWorklistEntry1020b57cec5SDimitry Andric Value *getDivisor() const { return DivInst->getOperand(1); }
1038bcb0991SDimitry Andric
isRemExpanded__anon5efc93f90211::DivRemPairWorklistEntry1048bcb0991SDimitry Andric bool isRemExpanded() const {
1058bcb0991SDimitry Andric switch (RemInst->getOpcode()) {
1068bcb0991SDimitry Andric case Instruction::SRem:
1078bcb0991SDimitry Andric case Instruction::URem:
1088bcb0991SDimitry Andric return false; // single 'rem' instruction - unexpanded form.
1098bcb0991SDimitry Andric default:
1108bcb0991SDimitry Andric return true; // anything else means we have remainder in expanded form.
1118bcb0991SDimitry Andric }
1128bcb0991SDimitry Andric }
1130b57cec5SDimitry Andric };
1145ffd83dbSDimitry Andric } // namespace
1150b57cec5SDimitry Andric using DivRemWorklistTy = SmallVector<DivRemPairWorklistEntry, 4>;
1160b57cec5SDimitry Andric
1170b57cec5SDimitry Andric /// Find matching pairs of integer div/rem ops (they have the same numerator,
1180b57cec5SDimitry Andric /// denominator, and signedness). Place those pairs into a worklist for further
1190b57cec5SDimitry Andric /// processing. This indirection is needed because we have to use TrackingVH<>
1200b57cec5SDimitry Andric /// because we will be doing RAUW, and if one of the rem instructions we change
1210b57cec5SDimitry Andric /// happens to be an input to another div/rem in the maps, we'd have problems.
getWorklist(Function & F)1220b57cec5SDimitry Andric static DivRemWorklistTy getWorklist(Function &F) {
1230b57cec5SDimitry Andric // Insert all divide and remainder instructions into maps keyed by their
1240b57cec5SDimitry Andric // operands and opcode (signed or unsigned).
1250b57cec5SDimitry Andric DenseMap<DivRemMapKey, Instruction *> DivMap;
1260b57cec5SDimitry Andric // Use a MapVector for RemMap so that instructions are moved/inserted in a
1270b57cec5SDimitry Andric // deterministic order.
1280b57cec5SDimitry Andric MapVector<DivRemMapKey, Instruction *> RemMap;
1290b57cec5SDimitry Andric for (auto &BB : F) {
1300b57cec5SDimitry Andric for (auto &I : BB) {
1310b57cec5SDimitry Andric if (I.getOpcode() == Instruction::SDiv)
1320b57cec5SDimitry Andric DivMap[DivRemMapKey(true, I.getOperand(0), I.getOperand(1))] = &I;
1330b57cec5SDimitry Andric else if (I.getOpcode() == Instruction::UDiv)
1340b57cec5SDimitry Andric DivMap[DivRemMapKey(false, I.getOperand(0), I.getOperand(1))] = &I;
1350b57cec5SDimitry Andric else if (I.getOpcode() == Instruction::SRem)
1360b57cec5SDimitry Andric RemMap[DivRemMapKey(true, I.getOperand(0), I.getOperand(1))] = &I;
1370b57cec5SDimitry Andric else if (I.getOpcode() == Instruction::URem)
1380b57cec5SDimitry Andric RemMap[DivRemMapKey(false, I.getOperand(0), I.getOperand(1))] = &I;
1398bcb0991SDimitry Andric else if (auto Match = matchExpandedRem(I))
1408bcb0991SDimitry Andric RemMap[Match->Key] = Match->Value;
1410b57cec5SDimitry Andric }
1420b57cec5SDimitry Andric }
1430b57cec5SDimitry Andric
1440b57cec5SDimitry Andric // We'll accumulate the matching pairs of div-rem instructions here.
1450b57cec5SDimitry Andric DivRemWorklistTy Worklist;
1460b57cec5SDimitry Andric
1470b57cec5SDimitry Andric // We can iterate over either map because we are only looking for matched
1480b57cec5SDimitry Andric // pairs. Choose remainders for efficiency because they are usually even more
1490b57cec5SDimitry Andric // rare than division.
1500b57cec5SDimitry Andric for (auto &RemPair : RemMap) {
1510b57cec5SDimitry Andric // Find the matching division instruction from the division map.
152e8d8bef9SDimitry Andric auto It = DivMap.find(RemPair.first);
153e8d8bef9SDimitry Andric if (It == DivMap.end())
1540b57cec5SDimitry Andric continue;
1550b57cec5SDimitry Andric
1560b57cec5SDimitry Andric // We have a matching pair of div/rem instructions.
1570b57cec5SDimitry Andric NumPairs++;
1580b57cec5SDimitry Andric Instruction *RemInst = RemPair.second;
1590b57cec5SDimitry Andric
1600b57cec5SDimitry Andric // Place it in the worklist.
161e8d8bef9SDimitry Andric Worklist.emplace_back(It->second, RemInst);
1620b57cec5SDimitry Andric }
1630b57cec5SDimitry Andric
1640b57cec5SDimitry Andric return Worklist;
1650b57cec5SDimitry Andric }
1660b57cec5SDimitry Andric
1670b57cec5SDimitry Andric /// Find matching pairs of integer div/rem ops (they have the same numerator,
1680b57cec5SDimitry Andric /// denominator, and signedness). If they exist in different basic blocks, bring
1690b57cec5SDimitry Andric /// them together by hoisting or replace the common division operation that is
1700b57cec5SDimitry Andric /// implicit in the remainder:
1710b57cec5SDimitry Andric /// X % Y <--> X - ((X / Y) * Y).
1720b57cec5SDimitry Andric ///
1730b57cec5SDimitry Andric /// We can largely ignore the normal safety and cost constraints on speculation
1740b57cec5SDimitry Andric /// of these ops when we find a matching pair. This is because we are already
1750b57cec5SDimitry Andric /// guaranteed that any exceptions and most cost are already incurred by the
1760b57cec5SDimitry Andric /// first member of the pair.
1770b57cec5SDimitry Andric ///
1780b57cec5SDimitry Andric /// Note: This transform could be an oddball enhancement to EarlyCSE, GVN, or
1790b57cec5SDimitry Andric /// SimplifyCFG, but it's split off on its own because it's different enough
1800b57cec5SDimitry Andric /// that it doesn't quite match the stated objectives of those passes.
optimizeDivRem(Function & F,const TargetTransformInfo & TTI,const DominatorTree & DT)1810b57cec5SDimitry Andric static bool optimizeDivRem(Function &F, const TargetTransformInfo &TTI,
1820b57cec5SDimitry Andric const DominatorTree &DT) {
1830b57cec5SDimitry Andric bool Changed = false;
1840b57cec5SDimitry Andric
1850b57cec5SDimitry Andric // Get the matching pairs of div-rem instructions. We want this extra
1860b57cec5SDimitry Andric // indirection to avoid dealing with having to RAUW the keys of the maps.
1870b57cec5SDimitry Andric DivRemWorklistTy Worklist = getWorklist(F);
1880b57cec5SDimitry Andric
1890b57cec5SDimitry Andric // Process each entry in the worklist.
1900b57cec5SDimitry Andric for (DivRemPairWorklistEntry &E : Worklist) {
1918bcb0991SDimitry Andric if (!DebugCounter::shouldExecute(DRPCounter))
1928bcb0991SDimitry Andric continue;
1938bcb0991SDimitry Andric
1940b57cec5SDimitry Andric bool HasDivRemOp = TTI.hasDivRemOp(E.getType(), E.isSigned());
1950b57cec5SDimitry Andric
1960b57cec5SDimitry Andric auto &DivInst = E.DivInst;
1970b57cec5SDimitry Andric auto &RemInst = E.RemInst;
1980b57cec5SDimitry Andric
1998bcb0991SDimitry Andric const bool RemOriginallyWasInExpandedForm = E.isRemExpanded();
2008bcb0991SDimitry Andric (void)RemOriginallyWasInExpandedForm; // suppress unused variable warning
2018bcb0991SDimitry Andric
2028bcb0991SDimitry Andric if (HasDivRemOp && E.isRemExpanded()) {
2038bcb0991SDimitry Andric // The target supports div+rem but the rem is expanded.
2048bcb0991SDimitry Andric // We should recompose it first.
2058bcb0991SDimitry Andric Value *X = E.getDividend();
2068bcb0991SDimitry Andric Value *Y = E.getDivisor();
2078bcb0991SDimitry Andric Instruction *RealRem = E.isSigned() ? BinaryOperator::CreateSRem(X, Y)
2088bcb0991SDimitry Andric : BinaryOperator::CreateURem(X, Y);
2098bcb0991SDimitry Andric // Note that we place it right next to the original expanded instruction,
2108bcb0991SDimitry Andric // and letting further handling to move it if needed.
2118bcb0991SDimitry Andric RealRem->setName(RemInst->getName() + ".recomposed");
2128bcb0991SDimitry Andric RealRem->insertAfter(RemInst);
2138bcb0991SDimitry Andric Instruction *OrigRemInst = RemInst;
2148bcb0991SDimitry Andric // Update AssertingVH<> with new instruction so it doesn't assert.
2158bcb0991SDimitry Andric RemInst = RealRem;
2168bcb0991SDimitry Andric // And replace the original instruction with the new one.
2178bcb0991SDimitry Andric OrigRemInst->replaceAllUsesWith(RealRem);
218*0fca6ea1SDimitry Andric RealRem->setDebugLoc(OrigRemInst->getDebugLoc());
2198bcb0991SDimitry Andric OrigRemInst->eraseFromParent();
2208bcb0991SDimitry Andric NumRecomposed++;
2218bcb0991SDimitry Andric // Note that we have left ((X / Y) * Y) around.
2228bcb0991SDimitry Andric // If it had other uses we could rewrite it as X - X % Y
2235ffd83dbSDimitry Andric Changed = true;
2248bcb0991SDimitry Andric }
2258bcb0991SDimitry Andric
2268bcb0991SDimitry Andric assert((!E.isRemExpanded() || !HasDivRemOp) &&
2278bcb0991SDimitry Andric "*If* the target supports div-rem, then by now the RemInst *is* "
2288bcb0991SDimitry Andric "Instruction::[US]Rem.");
2298bcb0991SDimitry Andric
2300b57cec5SDimitry Andric // If the target supports div+rem and the instructions are in the same block
2310b57cec5SDimitry Andric // already, there's nothing to do. The backend should handle this. If the
2320b57cec5SDimitry Andric // target does not support div+rem, then we will decompose the rem.
2330b57cec5SDimitry Andric if (HasDivRemOp && RemInst->getParent() == DivInst->getParent())
2340b57cec5SDimitry Andric continue;
2350b57cec5SDimitry Andric
2360b57cec5SDimitry Andric bool DivDominates = DT.dominates(DivInst, RemInst);
2378bcb0991SDimitry Andric if (!DivDominates && !DT.dominates(RemInst, DivInst)) {
2388bcb0991SDimitry Andric // We have matching div-rem pair, but they are in two different blocks,
2398bcb0991SDimitry Andric // neither of which dominates one another.
240fe6060f1SDimitry Andric
241fe6060f1SDimitry Andric BasicBlock *PredBB = nullptr;
242fe6060f1SDimitry Andric BasicBlock *DivBB = DivInst->getParent();
243fe6060f1SDimitry Andric BasicBlock *RemBB = RemInst->getParent();
244fe6060f1SDimitry Andric
245fe6060f1SDimitry Andric // It's only safe to hoist if every instruction before the Div/Rem in the
246fe6060f1SDimitry Andric // basic block is guaranteed to transfer execution.
247fe6060f1SDimitry Andric auto IsSafeToHoist = [](Instruction *DivOrRem, BasicBlock *ParentBB) {
248fe6060f1SDimitry Andric for (auto I = ParentBB->begin(), E = DivOrRem->getIterator(); I != E;
249fe6060f1SDimitry Andric ++I)
250fe6060f1SDimitry Andric if (!isGuaranteedToTransferExecutionToSuccessor(&*I))
251fe6060f1SDimitry Andric return false;
252fe6060f1SDimitry Andric
253fe6060f1SDimitry Andric return true;
254fe6060f1SDimitry Andric };
255fe6060f1SDimitry Andric
256fe6060f1SDimitry Andric // Look for something like this
257fe6060f1SDimitry Andric // PredBB
258fe6060f1SDimitry Andric // | \
259fe6060f1SDimitry Andric // | Rem
260fe6060f1SDimitry Andric // | /
261fe6060f1SDimitry Andric // Div
262fe6060f1SDimitry Andric //
263fe6060f1SDimitry Andric // If the Rem block has a single predecessor and successor, and all paths
264fe6060f1SDimitry Andric // from PredBB go to either RemBB or DivBB, and execution of RemBB and
265fe6060f1SDimitry Andric // DivBB will always reach the Div/Rem, we can hoist Div to PredBB. If
266fe6060f1SDimitry Andric // we have a DivRem operation we can also hoist Rem. Otherwise we'll leave
267fe6060f1SDimitry Andric // Rem where it is and rewrite it to mul/sub.
268bdd1243dSDimitry Andric if (RemBB->getSingleSuccessor() == DivBB) {
269fe6060f1SDimitry Andric PredBB = RemBB->getUniquePredecessor();
270fe6060f1SDimitry Andric
271bdd1243dSDimitry Andric // Look for something like this
272bdd1243dSDimitry Andric // PredBB
273bdd1243dSDimitry Andric // / \
274bdd1243dSDimitry Andric // Div Rem
275bdd1243dSDimitry Andric //
276bdd1243dSDimitry Andric // If the Rem and Din blocks share a unique predecessor, and all
277bdd1243dSDimitry Andric // paths from PredBB go to either RemBB or DivBB, and execution of RemBB
278bdd1243dSDimitry Andric // and DivBB will always reach the Div/Rem, we can hoist Div to PredBB.
279bdd1243dSDimitry Andric // If we have a DivRem operation we can also hoist Rem. By hoisting both
280bdd1243dSDimitry Andric // ops to the same block, we reduce code size and allow the DivRem to
281bdd1243dSDimitry Andric // issue sooner. Without a DivRem op, this transformation is
282bdd1243dSDimitry Andric // unprofitable because we would end up performing an extra Mul+Sub on
283bdd1243dSDimitry Andric // the Rem path.
284bdd1243dSDimitry Andric } else if (BasicBlock *RemPredBB = RemBB->getUniquePredecessor()) {
285bdd1243dSDimitry Andric // This hoist is only profitable when the target has a DivRem op.
286bdd1243dSDimitry Andric if (HasDivRemOp && RemPredBB == DivBB->getUniquePredecessor())
287bdd1243dSDimitry Andric PredBB = RemPredBB;
288bdd1243dSDimitry Andric }
289bdd1243dSDimitry Andric // FIXME: We could handle more hoisting cases.
290bdd1243dSDimitry Andric
291bdd1243dSDimitry Andric if (PredBB && !isa<CatchSwitchInst>(PredBB->getTerminator()) &&
292bdd1243dSDimitry Andric isGuaranteedToTransferExecutionToSuccessor(PredBB->getTerminator()) &&
293bdd1243dSDimitry Andric IsSafeToHoist(RemInst, RemBB) && IsSafeToHoist(DivInst, DivBB) &&
2946e75b2fbSDimitry Andric all_of(successors(PredBB),
2956e75b2fbSDimitry Andric [&](BasicBlock *BB) { return BB == DivBB || BB == RemBB; }) &&
2966e75b2fbSDimitry Andric all_of(predecessors(DivBB),
2976e75b2fbSDimitry Andric [&](BasicBlock *BB) { return BB == RemBB || BB == PredBB; })) {
298fe6060f1SDimitry Andric DivDominates = true;
299fe6060f1SDimitry Andric DivInst->moveBefore(PredBB->getTerminator());
300fe6060f1SDimitry Andric Changed = true;
301fe6060f1SDimitry Andric if (HasDivRemOp) {
302fe6060f1SDimitry Andric RemInst->moveBefore(PredBB->getTerminator());
303fe6060f1SDimitry Andric continue;
304fe6060f1SDimitry Andric }
305fe6060f1SDimitry Andric } else
3060b57cec5SDimitry Andric continue;
3078bcb0991SDimitry Andric }
3080b57cec5SDimitry Andric
3098bcb0991SDimitry Andric // The target does not have a single div/rem operation,
3108bcb0991SDimitry Andric // and the rem is already in expanded form. Nothing to do.
3118bcb0991SDimitry Andric if (!HasDivRemOp && E.isRemExpanded())
3120b57cec5SDimitry Andric continue;
3130b57cec5SDimitry Andric
3140b57cec5SDimitry Andric if (HasDivRemOp) {
3150b57cec5SDimitry Andric // The target has a single div/rem operation. Hoist the lower instruction
3160b57cec5SDimitry Andric // to make the matched pair visible to the backend.
3170b57cec5SDimitry Andric if (DivDominates)
3180b57cec5SDimitry Andric RemInst->moveAfter(DivInst);
3190b57cec5SDimitry Andric else
3200b57cec5SDimitry Andric DivInst->moveAfter(RemInst);
3210b57cec5SDimitry Andric NumHoisted++;
3220b57cec5SDimitry Andric } else {
3238bcb0991SDimitry Andric // The target does not have a single div/rem operation,
3248bcb0991SDimitry Andric // and the rem is *not* in a already-expanded form.
3258bcb0991SDimitry Andric // Decompose the remainder calculation as:
3260b57cec5SDimitry Andric // X % Y --> X - ((X / Y) * Y).
3278bcb0991SDimitry Andric
3288bcb0991SDimitry Andric assert(!RemOriginallyWasInExpandedForm &&
3298bcb0991SDimitry Andric "We should not be expanding if the rem was in expanded form to "
3308bcb0991SDimitry Andric "begin with.");
3318bcb0991SDimitry Andric
3320b57cec5SDimitry Andric Value *X = E.getDividend();
3330b57cec5SDimitry Andric Value *Y = E.getDivisor();
3340b57cec5SDimitry Andric Instruction *Mul = BinaryOperator::CreateMul(DivInst, Y);
3350b57cec5SDimitry Andric Instruction *Sub = BinaryOperator::CreateSub(X, Mul);
3360b57cec5SDimitry Andric
3370b57cec5SDimitry Andric // If the remainder dominates, then hoist the division up to that block:
3380b57cec5SDimitry Andric //
3390b57cec5SDimitry Andric // bb1:
3400b57cec5SDimitry Andric // %rem = srem %x, %y
3410b57cec5SDimitry Andric // bb2:
3420b57cec5SDimitry Andric // %div = sdiv %x, %y
3430b57cec5SDimitry Andric // -->
3440b57cec5SDimitry Andric // bb1:
3450b57cec5SDimitry Andric // %div = sdiv %x, %y
3460b57cec5SDimitry Andric // %mul = mul %div, %y
3470b57cec5SDimitry Andric // %rem = sub %x, %mul
3480b57cec5SDimitry Andric //
3490b57cec5SDimitry Andric // If the division dominates, it's already in the right place. The mul+sub
3500b57cec5SDimitry Andric // will be in a different block because we don't assume that they are
3510b57cec5SDimitry Andric // cheap to speculatively execute:
3520b57cec5SDimitry Andric //
3530b57cec5SDimitry Andric // bb1:
3540b57cec5SDimitry Andric // %div = sdiv %x, %y
3550b57cec5SDimitry Andric // bb2:
3560b57cec5SDimitry Andric // %rem = srem %x, %y
3570b57cec5SDimitry Andric // -->
3580b57cec5SDimitry Andric // bb1:
3590b57cec5SDimitry Andric // %div = sdiv %x, %y
3600b57cec5SDimitry Andric // bb2:
3610b57cec5SDimitry Andric // %mul = mul %div, %y
3620b57cec5SDimitry Andric // %rem = sub %x, %mul
3630b57cec5SDimitry Andric //
3640b57cec5SDimitry Andric // If the div and rem are in the same block, we do the same transform,
3650b57cec5SDimitry Andric // but any code movement would be within the same block.
3660b57cec5SDimitry Andric
3670b57cec5SDimitry Andric if (!DivDominates)
3680b57cec5SDimitry Andric DivInst->moveBefore(RemInst);
3690b57cec5SDimitry Andric Mul->insertAfter(RemInst);
370*0fca6ea1SDimitry Andric Mul->setDebugLoc(RemInst->getDebugLoc());
3710b57cec5SDimitry Andric Sub->insertAfter(Mul);
372*0fca6ea1SDimitry Andric Sub->setDebugLoc(RemInst->getDebugLoc());
3730b57cec5SDimitry Andric
37406c3fb27SDimitry Andric // If DivInst has the exact flag, remove it. Otherwise this optimization
37506c3fb27SDimitry Andric // may replace a well-defined value 'X % Y' with poison.
37606c3fb27SDimitry Andric DivInst->dropPoisonGeneratingFlags();
37706c3fb27SDimitry Andric
3785ffd83dbSDimitry Andric // If X can be undef, X should be frozen first.
3795ffd83dbSDimitry Andric // For example, let's assume that Y = 1 & X = undef:
3805ffd83dbSDimitry Andric // %div = sdiv undef, 1 // %div = undef
3815ffd83dbSDimitry Andric // %rem = srem undef, 1 // %rem = 0
3825ffd83dbSDimitry Andric // =>
3835ffd83dbSDimitry Andric // %div = sdiv undef, 1 // %div = undef
3845ffd83dbSDimitry Andric // %mul = mul %div, 1 // %mul = undef
3855ffd83dbSDimitry Andric // %rem = sub %x, %mul // %rem = undef - undef = undef
3865ffd83dbSDimitry Andric // If X is not frozen, %rem becomes undef after transformation.
387*0fca6ea1SDimitry Andric if (!isGuaranteedNotToBeUndef(X, nullptr, DivInst, &DT)) {
388*0fca6ea1SDimitry Andric auto *FrX =
389*0fca6ea1SDimitry Andric new FreezeInst(X, X->getName() + ".frozen", DivInst->getIterator());
390*0fca6ea1SDimitry Andric FrX->setDebugLoc(DivInst->getDebugLoc());
3915ffd83dbSDimitry Andric DivInst->setOperand(0, FrX);
3925ffd83dbSDimitry Andric Sub->setOperand(0, FrX);
3935ffd83dbSDimitry Andric }
3945ffd83dbSDimitry Andric // Same for Y. If X = 1 and Y = (undef | 1), %rem in src is either 1 or 0,
3955ffd83dbSDimitry Andric // but %rem in tgt can be one of many integer values.
396*0fca6ea1SDimitry Andric if (!isGuaranteedNotToBeUndef(Y, nullptr, DivInst, &DT)) {
397*0fca6ea1SDimitry Andric auto *FrY =
398*0fca6ea1SDimitry Andric new FreezeInst(Y, Y->getName() + ".frozen", DivInst->getIterator());
399*0fca6ea1SDimitry Andric FrY->setDebugLoc(DivInst->getDebugLoc());
4005ffd83dbSDimitry Andric DivInst->setOperand(1, FrY);
4015ffd83dbSDimitry Andric Mul->setOperand(1, FrY);
4025ffd83dbSDimitry Andric }
4035ffd83dbSDimitry Andric
4040b57cec5SDimitry Andric // Now kill the explicit remainder. We have replaced it with:
4050b57cec5SDimitry Andric // (sub X, (mul (div X, Y), Y)
4060b57cec5SDimitry Andric Sub->setName(RemInst->getName() + ".decomposed");
4070b57cec5SDimitry Andric Instruction *OrigRemInst = RemInst;
4080b57cec5SDimitry Andric // Update AssertingVH<> with new instruction so it doesn't assert.
4090b57cec5SDimitry Andric RemInst = Sub;
4100b57cec5SDimitry Andric // And replace the original instruction with the new one.
4110b57cec5SDimitry Andric OrigRemInst->replaceAllUsesWith(Sub);
4120b57cec5SDimitry Andric OrigRemInst->eraseFromParent();
4130b57cec5SDimitry Andric NumDecomposed++;
4140b57cec5SDimitry Andric }
4150b57cec5SDimitry Andric Changed = true;
4160b57cec5SDimitry Andric }
4170b57cec5SDimitry Andric
4180b57cec5SDimitry Andric return Changed;
4190b57cec5SDimitry Andric }
4200b57cec5SDimitry Andric
4210b57cec5SDimitry Andric // Pass manager boilerplate below here.
4220b57cec5SDimitry Andric
run(Function & F,FunctionAnalysisManager & FAM)4230b57cec5SDimitry Andric PreservedAnalyses DivRemPairsPass::run(Function &F,
4240b57cec5SDimitry Andric FunctionAnalysisManager &FAM) {
4250b57cec5SDimitry Andric TargetTransformInfo &TTI = FAM.getResult<TargetIRAnalysis>(F);
4260b57cec5SDimitry Andric DominatorTree &DT = FAM.getResult<DominatorTreeAnalysis>(F);
4270b57cec5SDimitry Andric if (!optimizeDivRem(F, TTI, DT))
4280b57cec5SDimitry Andric return PreservedAnalyses::all();
4290b57cec5SDimitry Andric // TODO: This pass just hoists/replaces math ops - all analyses are preserved?
4300b57cec5SDimitry Andric PreservedAnalyses PA;
4310b57cec5SDimitry Andric PA.preserveSet<CFGAnalyses>();
4320b57cec5SDimitry Andric return PA;
4330b57cec5SDimitry Andric }
434