xref: /freebsd/contrib/llvm-project/llvm/lib/Transforms/Scalar/DivRemPairs.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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