xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/Scalar/GVNHoist.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- GVNHoist.cpp - Hoist scalar and load expressions -------------------===//
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 //
90b57cec5SDimitry Andric // This pass hoists expressions from branches to a common dominator. It uses
100b57cec5SDimitry Andric // GVN (global value numbering) to discover expressions computing the same
110b57cec5SDimitry Andric // values. The primary goals of code-hoisting are:
120b57cec5SDimitry Andric // 1. To reduce the code size.
130b57cec5SDimitry Andric // 2. In some cases reduce critical path (by exposing more ILP).
140b57cec5SDimitry Andric //
150b57cec5SDimitry Andric // The algorithm factors out the reachability of values such that multiple
160b57cec5SDimitry Andric // queries to find reachability of values are fast. This is based on finding the
170b57cec5SDimitry Andric // ANTIC points in the CFG which do not change during hoisting. The ANTIC points
180b57cec5SDimitry Andric // are basically the dominance-frontiers in the inverse graph. So we introduce a
190b57cec5SDimitry Andric // data structure (CHI nodes) to keep track of values flowing out of a basic
200b57cec5SDimitry Andric // block. We only do this for values with multiple occurrences in the function
210b57cec5SDimitry Andric // as they are the potential hoistable candidates. This approach allows us to
220b57cec5SDimitry Andric // hoist instructions to a basic block with more than two successors, as well as
230b57cec5SDimitry Andric // deal with infinite loops in a trivial way.
240b57cec5SDimitry Andric //
250b57cec5SDimitry Andric // Limitations: This pass does not hoist fully redundant expressions because
260b57cec5SDimitry Andric // they are already handled by GVN-PRE. It is advisable to run gvn-hoist before
270b57cec5SDimitry Andric // and after gvn-pre because gvn-pre creates opportunities for more instructions
280b57cec5SDimitry Andric // to be hoisted.
290b57cec5SDimitry Andric //
300b57cec5SDimitry Andric // Hoisting may affect the performance in some cases. To mitigate that, hoisting
310b57cec5SDimitry Andric // is disabled in the following cases.
320b57cec5SDimitry Andric // 1. Scalars across calls.
330b57cec5SDimitry Andric // 2. geps when corresponding load/store cannot be hoisted.
340b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
370b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h"
380b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
390b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
400b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
410b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
420b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h"
430b57cec5SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h"
440b57cec5SDimitry Andric #include "llvm/Analysis/GlobalsModRef.h"
450b57cec5SDimitry Andric #include "llvm/Analysis/IteratedDominanceFrontier.h"
460b57cec5SDimitry Andric #include "llvm/Analysis/MemoryDependenceAnalysis.h"
470b57cec5SDimitry Andric #include "llvm/Analysis/MemorySSA.h"
480b57cec5SDimitry Andric #include "llvm/Analysis/MemorySSAUpdater.h"
490b57cec5SDimitry Andric #include "llvm/Analysis/PostDominators.h"
500b57cec5SDimitry Andric #include "llvm/Analysis/ValueTracking.h"
510b57cec5SDimitry Andric #include "llvm/IR/Argument.h"
520b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h"
530b57cec5SDimitry Andric #include "llvm/IR/CFG.h"
540b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
550b57cec5SDimitry Andric #include "llvm/IR/Dominators.h"
560b57cec5SDimitry Andric #include "llvm/IR/Function.h"
570b57cec5SDimitry Andric #include "llvm/IR/Instruction.h"
580b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
590b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
600b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h"
610b57cec5SDimitry Andric #include "llvm/IR/PassManager.h"
620b57cec5SDimitry Andric #include "llvm/IR/Use.h"
630b57cec5SDimitry Andric #include "llvm/IR/User.h"
640b57cec5SDimitry Andric #include "llvm/IR/Value.h"
650b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
660b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
670b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
680b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
690b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/GVN.h"
70480093f4SDimitry Andric #include "llvm/Transforms/Utils/Local.h"
710b57cec5SDimitry Andric #include <algorithm>
720b57cec5SDimitry Andric #include <cassert>
730b57cec5SDimitry Andric #include <iterator>
740b57cec5SDimitry Andric #include <memory>
750b57cec5SDimitry Andric #include <utility>
760b57cec5SDimitry Andric #include <vector>
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric using namespace llvm;
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric #define DEBUG_TYPE "gvn-hoist"
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric STATISTIC(NumHoisted, "Number of instructions hoisted");
830b57cec5SDimitry Andric STATISTIC(NumRemoved, "Number of instructions removed");
840b57cec5SDimitry Andric STATISTIC(NumLoadsHoisted, "Number of loads hoisted");
850b57cec5SDimitry Andric STATISTIC(NumLoadsRemoved, "Number of loads removed");
860b57cec5SDimitry Andric STATISTIC(NumStoresHoisted, "Number of stores hoisted");
870b57cec5SDimitry Andric STATISTIC(NumStoresRemoved, "Number of stores removed");
880b57cec5SDimitry Andric STATISTIC(NumCallsHoisted, "Number of calls hoisted");
890b57cec5SDimitry Andric STATISTIC(NumCallsRemoved, "Number of calls removed");
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric static cl::opt<int>
920b57cec5SDimitry Andric     MaxHoistedThreshold("gvn-max-hoisted", cl::Hidden, cl::init(-1),
930b57cec5SDimitry Andric                         cl::desc("Max number of instructions to hoist "
940b57cec5SDimitry Andric                                  "(default unlimited = -1)"));
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric static cl::opt<int> MaxNumberOfBBSInPath(
970b57cec5SDimitry Andric     "gvn-hoist-max-bbs", cl::Hidden, cl::init(4),
980b57cec5SDimitry Andric     cl::desc("Max number of basic blocks on the path between "
990b57cec5SDimitry Andric              "hoisting locations (default = 4, unlimited = -1)"));
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric static cl::opt<int> MaxDepthInBB(
1020b57cec5SDimitry Andric     "gvn-hoist-max-depth", cl::Hidden, cl::init(100),
1030b57cec5SDimitry Andric     cl::desc("Hoist instructions from the beginning of the BB up to the "
1040b57cec5SDimitry Andric              "maximum specified depth (default = 100, unlimited = -1)"));
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric static cl::opt<int>
1070b57cec5SDimitry Andric     MaxChainLength("gvn-hoist-max-chain-length", cl::Hidden, cl::init(10),
1080b57cec5SDimitry Andric                    cl::desc("Maximum length of dependent chains to hoist "
1090b57cec5SDimitry Andric                             "(default = 10, unlimited = -1)"));
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric namespace llvm {
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric using BBSideEffectsSet = DenseMap<const BasicBlock *, bool>;
1140b57cec5SDimitry Andric using SmallVecInsn = SmallVector<Instruction *, 4>;
1150b57cec5SDimitry Andric using SmallVecImplInsn = SmallVectorImpl<Instruction *>;
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric // Each element of a hoisting list contains the basic block where to hoist and
1180b57cec5SDimitry Andric // a list of instructions to be hoisted.
1190b57cec5SDimitry Andric using HoistingPointInfo = std::pair<BasicBlock *, SmallVecInsn>;
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric using HoistingPointList = SmallVector<HoistingPointInfo, 4>;
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric // A map from a pair of VNs to all the instructions with those VNs.
12481ad6265SDimitry Andric using VNType = std::pair<unsigned, uintptr_t>;
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric using VNtoInsns = DenseMap<VNType, SmallVector<Instruction *, 4>>;
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric // CHI keeps information about values flowing out of a basic block.  It is
1290b57cec5SDimitry Andric // similar to PHI but in the inverse graph, and used for outgoing values on each
1300b57cec5SDimitry Andric // edge. For conciseness, it is computed only for instructions with multiple
1310b57cec5SDimitry Andric // occurrences in the CFG because they are the only hoistable candidates.
1320b57cec5SDimitry Andric //     A (CHI[{V, B, I1}, {V, C, I2}]
1330b57cec5SDimitry Andric //  /     \
1340b57cec5SDimitry Andric // /       \
1350b57cec5SDimitry Andric // B(I1)  C (I2)
1360b57cec5SDimitry Andric // The Value number for both I1 and I2 is V, the CHI node will save the
1370b57cec5SDimitry Andric // instruction as well as the edge where the value is flowing to.
1380b57cec5SDimitry Andric struct CHIArg {
1390b57cec5SDimitry Andric   VNType VN;
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   // Edge destination (shows the direction of flow), may not be where the I is.
1420b57cec5SDimitry Andric   BasicBlock *Dest;
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric   // The instruction (VN) which uses the values flowing out of CHI.
1450b57cec5SDimitry Andric   Instruction *I;
1460b57cec5SDimitry Andric 
147e8d8bef9SDimitry Andric   bool operator==(const CHIArg &A) const { return VN == A.VN; }
148e8d8bef9SDimitry Andric   bool operator!=(const CHIArg &A) const { return !(*this == A); }
1490b57cec5SDimitry Andric };
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric using CHIIt = SmallVectorImpl<CHIArg>::iterator;
1520b57cec5SDimitry Andric using CHIArgs = iterator_range<CHIIt>;
1530b57cec5SDimitry Andric using OutValuesType = DenseMap<BasicBlock *, SmallVector<CHIArg, 2>>;
1540b57cec5SDimitry Andric using InValuesType =
1550b57cec5SDimitry Andric     DenseMap<BasicBlock *, SmallVector<std::pair<VNType, Instruction *>, 2>>;
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric // An invalid value number Used when inserting a single value number into
1580b57cec5SDimitry Andric // VNtoInsns.
15981ad6265SDimitry Andric enum : uintptr_t { InvalidVN = ~(uintptr_t)2 };
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric // Records all scalar instructions candidate for code hoisting.
1620b57cec5SDimitry Andric class InsnInfo {
1630b57cec5SDimitry Andric   VNtoInsns VNtoScalars;
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric public:
1660b57cec5SDimitry Andric   // Inserts I and its value number in VNtoScalars.
167349cc55cSDimitry Andric   void insert(Instruction *I, GVNPass::ValueTable &VN) {
1680b57cec5SDimitry Andric     // Scalar instruction.
1690b57cec5SDimitry Andric     unsigned V = VN.lookupOrAdd(I);
1700b57cec5SDimitry Andric     VNtoScalars[{V, InvalidVN}].push_back(I);
1710b57cec5SDimitry Andric   }
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric   const VNtoInsns &getVNTable() const { return VNtoScalars; }
1740b57cec5SDimitry Andric };
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric // Records all load instructions candidate for code hoisting.
1770b57cec5SDimitry Andric class LoadInfo {
1780b57cec5SDimitry Andric   VNtoInsns VNtoLoads;
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric public:
1810b57cec5SDimitry Andric   // Insert Load and the value number of its memory address in VNtoLoads.
182349cc55cSDimitry Andric   void insert(LoadInst *Load, GVNPass::ValueTable &VN) {
1830b57cec5SDimitry Andric     if (Load->isSimple()) {
1840b57cec5SDimitry Andric       unsigned V = VN.lookupOrAdd(Load->getPointerOperand());
18581ad6265SDimitry Andric       // With opaque pointers we may have loads from the same pointer with
18681ad6265SDimitry Andric       // different result types, which should be disambiguated.
18781ad6265SDimitry Andric       VNtoLoads[{V, (uintptr_t)Load->getType()}].push_back(Load);
1880b57cec5SDimitry Andric     }
1890b57cec5SDimitry Andric   }
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric   const VNtoInsns &getVNTable() const { return VNtoLoads; }
1920b57cec5SDimitry Andric };
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric // Records all store instructions candidate for code hoisting.
1950b57cec5SDimitry Andric class StoreInfo {
1960b57cec5SDimitry Andric   VNtoInsns VNtoStores;
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric public:
1990b57cec5SDimitry Andric   // Insert the Store and a hash number of the store address and the stored
2000b57cec5SDimitry Andric   // value in VNtoStores.
201349cc55cSDimitry Andric   void insert(StoreInst *Store, GVNPass::ValueTable &VN) {
2020b57cec5SDimitry Andric     if (!Store->isSimple())
2030b57cec5SDimitry Andric       return;
2040b57cec5SDimitry Andric     // Hash the store address and the stored value.
2050b57cec5SDimitry Andric     Value *Ptr = Store->getPointerOperand();
2060b57cec5SDimitry Andric     Value *Val = Store->getValueOperand();
2070b57cec5SDimitry Andric     VNtoStores[{VN.lookupOrAdd(Ptr), VN.lookupOrAdd(Val)}].push_back(Store);
2080b57cec5SDimitry Andric   }
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric   const VNtoInsns &getVNTable() const { return VNtoStores; }
2110b57cec5SDimitry Andric };
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric // Records all call instructions candidate for code hoisting.
2140b57cec5SDimitry Andric class CallInfo {
2150b57cec5SDimitry Andric   VNtoInsns VNtoCallsScalars;
2160b57cec5SDimitry Andric   VNtoInsns VNtoCallsLoads;
2170b57cec5SDimitry Andric   VNtoInsns VNtoCallsStores;
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric public:
2200b57cec5SDimitry Andric   // Insert Call and its value numbering in one of the VNtoCalls* containers.
221349cc55cSDimitry Andric   void insert(CallInst *Call, GVNPass::ValueTable &VN) {
2220b57cec5SDimitry Andric     // A call that doesNotAccessMemory is handled as a Scalar,
2230b57cec5SDimitry Andric     // onlyReadsMemory will be handled as a Load instruction,
2240b57cec5SDimitry Andric     // all other calls will be handled as stores.
2250b57cec5SDimitry Andric     unsigned V = VN.lookupOrAdd(Call);
2260b57cec5SDimitry Andric     auto Entry = std::make_pair(V, InvalidVN);
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric     if (Call->doesNotAccessMemory())
2290b57cec5SDimitry Andric       VNtoCallsScalars[Entry].push_back(Call);
2300b57cec5SDimitry Andric     else if (Call->onlyReadsMemory())
2310b57cec5SDimitry Andric       VNtoCallsLoads[Entry].push_back(Call);
2320b57cec5SDimitry Andric     else
2330b57cec5SDimitry Andric       VNtoCallsStores[Entry].push_back(Call);
2340b57cec5SDimitry Andric   }
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric   const VNtoInsns &getScalarVNTable() const { return VNtoCallsScalars; }
2370b57cec5SDimitry Andric   const VNtoInsns &getLoadVNTable() const { return VNtoCallsLoads; }
2380b57cec5SDimitry Andric   const VNtoInsns &getStoreVNTable() const { return VNtoCallsStores; }
2390b57cec5SDimitry Andric };
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric // This pass hoists common computations across branches sharing common
2420b57cec5SDimitry Andric // dominator. The primary goal is to reduce the code size, and in some
2430b57cec5SDimitry Andric // cases reduce critical path (by exposing more ILP).
2440b57cec5SDimitry Andric class GVNHoist {
2450b57cec5SDimitry Andric public:
2460b57cec5SDimitry Andric   GVNHoist(DominatorTree *DT, PostDominatorTree *PDT, AliasAnalysis *AA,
2470b57cec5SDimitry Andric            MemoryDependenceResults *MD, MemorySSA *MSSA)
2480b57cec5SDimitry Andric       : DT(DT), PDT(PDT), AA(AA), MD(MD), MSSA(MSSA),
24981ad6265SDimitry Andric         MSSAUpdater(std::make_unique<MemorySSAUpdater>(MSSA)) {
25081ad6265SDimitry Andric     MSSA->ensureOptimizedUses();
25181ad6265SDimitry Andric   }
2520b57cec5SDimitry Andric 
253e8d8bef9SDimitry Andric   bool run(Function &F);
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric   // Copied from NewGVN.cpp
2560b57cec5SDimitry Andric   // This function provides global ranking of operations so that we can place
2570b57cec5SDimitry Andric   // them in a canonical order.  Note that rank alone is not necessarily enough
2580b57cec5SDimitry Andric   // for a complete ordering, as constants all have the same rank.  However,
2590b57cec5SDimitry Andric   // generally, we will simplify an operation with all constants so that it
2600b57cec5SDimitry Andric   // doesn't matter what order they appear in.
261e8d8bef9SDimitry Andric   unsigned int rank(const Value *V) const;
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric private:
264349cc55cSDimitry Andric   GVNPass::ValueTable VN;
2650b57cec5SDimitry Andric   DominatorTree *DT;
2660b57cec5SDimitry Andric   PostDominatorTree *PDT;
2670b57cec5SDimitry Andric   AliasAnalysis *AA;
2680b57cec5SDimitry Andric   MemoryDependenceResults *MD;
2690b57cec5SDimitry Andric   MemorySSA *MSSA;
2700b57cec5SDimitry Andric   std::unique_ptr<MemorySSAUpdater> MSSAUpdater;
2710b57cec5SDimitry Andric   DenseMap<const Value *, unsigned> DFSNumber;
2720b57cec5SDimitry Andric   BBSideEffectsSet BBSideEffects;
2730b57cec5SDimitry Andric   DenseSet<const BasicBlock *> HoistBarrier;
2740b57cec5SDimitry Andric   SmallVector<BasicBlock *, 32> IDFBlocks;
2750b57cec5SDimitry Andric   unsigned NumFuncArgs;
2760b57cec5SDimitry Andric   const bool HoistingGeps = false;
2770b57cec5SDimitry Andric 
2780b57cec5SDimitry Andric   enum InsKind { Unknown, Scalar, Load, Store };
2790b57cec5SDimitry Andric 
2800b57cec5SDimitry Andric   // Return true when there are exception handling in BB.
281e8d8bef9SDimitry Andric   bool hasEH(const BasicBlock *BB);
2820b57cec5SDimitry Andric 
2830b57cec5SDimitry Andric   // Return true when I1 appears before I2 in the instructions of BB.
2840b57cec5SDimitry Andric   bool firstInBB(const Instruction *I1, const Instruction *I2) {
2850b57cec5SDimitry Andric     assert(I1->getParent() == I2->getParent());
2860b57cec5SDimitry Andric     unsigned I1DFS = DFSNumber.lookup(I1);
2870b57cec5SDimitry Andric     unsigned I2DFS = DFSNumber.lookup(I2);
2880b57cec5SDimitry Andric     assert(I1DFS && I2DFS);
2890b57cec5SDimitry Andric     return I1DFS < I2DFS;
2900b57cec5SDimitry Andric   }
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric   // Return true when there are memory uses of Def in BB.
2930b57cec5SDimitry Andric   bool hasMemoryUse(const Instruction *NewPt, MemoryDef *Def,
294e8d8bef9SDimitry Andric                     const BasicBlock *BB);
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric   bool hasEHhelper(const BasicBlock *BB, const BasicBlock *SrcBB,
297e8d8bef9SDimitry Andric                    int &NBBsOnAllPaths);
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric   // Return true when there are exception handling or loads of memory Def
3000b57cec5SDimitry Andric   // between Def and NewPt.  This function is only called for stores: Def is
3010b57cec5SDimitry Andric   // the MemoryDef of the store to be hoisted.
3020b57cec5SDimitry Andric 
3030b57cec5SDimitry Andric   // Decrement by 1 NBBsOnAllPaths for each block between HoistPt and BB, and
3040b57cec5SDimitry Andric   // return true when the counter NBBsOnAllPaths reaces 0, except when it is
3050b57cec5SDimitry Andric   // initialized to -1 which is unlimited.
3060b57cec5SDimitry Andric   bool hasEHOrLoadsOnPath(const Instruction *NewPt, MemoryDef *Def,
307e8d8bef9SDimitry Andric                           int &NBBsOnAllPaths);
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric   // Return true when there are exception handling between HoistPt and BB.
3100b57cec5SDimitry Andric   // Decrement by 1 NBBsOnAllPaths for each block between HoistPt and BB, and
3110b57cec5SDimitry Andric   // return true when the counter NBBsOnAllPaths reaches 0, except when it is
3120b57cec5SDimitry Andric   // initialized to -1 which is unlimited.
3130b57cec5SDimitry Andric   bool hasEHOnPath(const BasicBlock *HoistPt, const BasicBlock *SrcBB,
314e8d8bef9SDimitry Andric                    int &NBBsOnAllPaths);
3150b57cec5SDimitry Andric 
3160b57cec5SDimitry Andric   // Return true when it is safe to hoist a memory load or store U from OldPt
3170b57cec5SDimitry Andric   // to NewPt.
3180b57cec5SDimitry Andric   bool safeToHoistLdSt(const Instruction *NewPt, const Instruction *OldPt,
319e8d8bef9SDimitry Andric                        MemoryUseOrDef *U, InsKind K, int &NBBsOnAllPaths);
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric   // Return true when it is safe to hoist scalar instructions from all blocks in
3220b57cec5SDimitry Andric   // WL to HoistBB.
3230b57cec5SDimitry Andric   bool safeToHoistScalar(const BasicBlock *HoistBB, const BasicBlock *BB,
3240b57cec5SDimitry Andric                          int &NBBsOnAllPaths) {
3250b57cec5SDimitry Andric     return !hasEHOnPath(HoistBB, BB, NBBsOnAllPaths);
3260b57cec5SDimitry Andric   }
3270b57cec5SDimitry Andric 
3280b57cec5SDimitry Andric   // In the inverse CFG, the dominance frontier of basic block (BB) is the
3290b57cec5SDimitry Andric   // point where ANTIC needs to be computed for instructions which are going
3300b57cec5SDimitry Andric   // to be hoisted. Since this point does not change during gvn-hoist,
3310b57cec5SDimitry Andric   // we compute it only once (on demand).
3320b57cec5SDimitry Andric   // The ides is inspired from:
3330b57cec5SDimitry Andric   // "Partial Redundancy Elimination in SSA Form"
3340b57cec5SDimitry Andric   // ROBERT KENNEDY, SUN CHAN, SHIN-MING LIU, RAYMOND LO, PENG TU and FRED CHOW
3350b57cec5SDimitry Andric   // They use similar idea in the forward graph to find fully redundant and
3360b57cec5SDimitry Andric   // partially redundant expressions, here it is used in the inverse graph to
3370b57cec5SDimitry Andric   // find fully anticipable instructions at merge point (post-dominator in
3380b57cec5SDimitry Andric   // the inverse CFG).
3390b57cec5SDimitry Andric   // Returns the edge via which an instruction in BB will get the values from.
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric   // Returns true when the values are flowing out to each edge.
342e8d8bef9SDimitry Andric   bool valueAnticipable(CHIArgs C, Instruction *TI) const;
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric   // Check if it is safe to hoist values tracked by CHI in the range
3450b57cec5SDimitry Andric   // [Begin, End) and accumulate them in Safe.
3460b57cec5SDimitry Andric   void checkSafety(CHIArgs C, BasicBlock *BB, InsKind K,
347e8d8bef9SDimitry Andric                    SmallVectorImpl<CHIArg> &Safe);
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric   using RenameStackType = DenseMap<VNType, SmallVector<Instruction *, 2>>;
3500b57cec5SDimitry Andric 
3510b57cec5SDimitry Andric   // Push all the VNs corresponding to BB into RenameStack.
3520b57cec5SDimitry Andric   void fillRenameStack(BasicBlock *BB, InValuesType &ValueBBs,
353e8d8bef9SDimitry Andric                        RenameStackType &RenameStack);
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric   void fillChiArgs(BasicBlock *BB, OutValuesType &CHIBBs,
356e8d8bef9SDimitry Andric                    RenameStackType &RenameStack);
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric   // Walk the post-dominator tree top-down and use a stack for each value to
3590b57cec5SDimitry Andric   // store the last value you see. When you hit a CHI from a given edge, the
3600b57cec5SDimitry Andric   // value to use as the argument is at the top of the stack, add the value to
3610b57cec5SDimitry Andric   // CHI and pop.
3620b57cec5SDimitry Andric   void insertCHI(InValuesType &ValueBBs, OutValuesType &CHIBBs) {
3630b57cec5SDimitry Andric     auto Root = PDT->getNode(nullptr);
3640b57cec5SDimitry Andric     if (!Root)
3650b57cec5SDimitry Andric       return;
3660b57cec5SDimitry Andric     // Depth first walk on PDom tree to fill the CHIargs at each PDF.
367bdd1243dSDimitry Andric     for (auto *Node : depth_first(Root)) {
3680b57cec5SDimitry Andric       BasicBlock *BB = Node->getBlock();
3690b57cec5SDimitry Andric       if (!BB)
3700b57cec5SDimitry Andric         continue;
3710b57cec5SDimitry Andric 
372349cc55cSDimitry Andric       RenameStackType RenameStack;
3730b57cec5SDimitry Andric       // Collect all values in BB and push to stack.
3740b57cec5SDimitry Andric       fillRenameStack(BB, ValueBBs, RenameStack);
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric       // Fill outgoing values in each CHI corresponding to BB.
3770b57cec5SDimitry Andric       fillChiArgs(BB, CHIBBs, RenameStack);
3780b57cec5SDimitry Andric     }
3790b57cec5SDimitry Andric   }
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric   // Walk all the CHI-nodes to find ones which have a empty-entry and remove
3820b57cec5SDimitry Andric   // them Then collect all the instructions which are safe to hoist and see if
3830b57cec5SDimitry Andric   // they form a list of anticipable values. OutValues contains CHIs
3840b57cec5SDimitry Andric   // corresponding to each basic block.
3850b57cec5SDimitry Andric   void findHoistableCandidates(OutValuesType &CHIBBs, InsKind K,
386e8d8bef9SDimitry Andric                                HoistingPointList &HPL);
3870b57cec5SDimitry Andric 
3880b57cec5SDimitry Andric   // Compute insertion points for each values which can be fully anticipated at
3890b57cec5SDimitry Andric   // a dominator. HPL contains all such values.
3900b57cec5SDimitry Andric   void computeInsertionPoints(const VNtoInsns &Map, HoistingPointList &HPL,
3910b57cec5SDimitry Andric                               InsKind K) {
3920b57cec5SDimitry Andric     // Sort VNs based on their rankings
3930b57cec5SDimitry Andric     std::vector<VNType> Ranks;
3940b57cec5SDimitry Andric     for (const auto &Entry : Map) {
3950b57cec5SDimitry Andric       Ranks.push_back(Entry.first);
3960b57cec5SDimitry Andric     }
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric     // TODO: Remove fully-redundant expressions.
3990b57cec5SDimitry Andric     // Get instruction from the Map, assume that all the Instructions
4000b57cec5SDimitry Andric     // with same VNs have same rank (this is an approximation).
4010b57cec5SDimitry Andric     llvm::sort(Ranks, [this, &Map](const VNType &r1, const VNType &r2) {
4020b57cec5SDimitry Andric       return (rank(*Map.lookup(r1).begin()) < rank(*Map.lookup(r2).begin()));
4030b57cec5SDimitry Andric     });
4040b57cec5SDimitry Andric 
4050b57cec5SDimitry Andric     // - Sort VNs according to their rank, and start with lowest ranked VN
4060b57cec5SDimitry Andric     // - Take a VN and for each instruction with same VN
4070b57cec5SDimitry Andric     //   - Find the dominance frontier in the inverse graph (PDF)
4080b57cec5SDimitry Andric     //   - Insert the chi-node at PDF
4090b57cec5SDimitry Andric     // - Remove the chi-nodes with missing entries
4100b57cec5SDimitry Andric     // - Remove values from CHI-nodes which do not truly flow out, e.g.,
4110b57cec5SDimitry Andric     //   modified along the path.
4120b57cec5SDimitry Andric     // - Collect the remaining values that are still anticipable
4130b57cec5SDimitry Andric     SmallVector<BasicBlock *, 2> IDFBlocks;
4140b57cec5SDimitry Andric     ReverseIDFCalculator IDFs(*PDT);
4150b57cec5SDimitry Andric     OutValuesType OutValue;
4160b57cec5SDimitry Andric     InValuesType InValue;
4170b57cec5SDimitry Andric     for (const auto &R : Ranks) {
4180b57cec5SDimitry Andric       const SmallVecInsn &V = Map.lookup(R);
4190b57cec5SDimitry Andric       if (V.size() < 2)
4200b57cec5SDimitry Andric         continue;
4210b57cec5SDimitry Andric       const VNType &VN = R;
4220b57cec5SDimitry Andric       SmallPtrSet<BasicBlock *, 2> VNBlocks;
423bdd1243dSDimitry Andric       for (const auto &I : V) {
4240b57cec5SDimitry Andric         BasicBlock *BBI = I->getParent();
4250b57cec5SDimitry Andric         if (!hasEH(BBI))
4260b57cec5SDimitry Andric           VNBlocks.insert(BBI);
4270b57cec5SDimitry Andric       }
4280b57cec5SDimitry Andric       // Compute the Post Dominance Frontiers of each basic block
4290b57cec5SDimitry Andric       // The dominance frontier of a live block X in the reverse
4300b57cec5SDimitry Andric       // control graph is the set of blocks upon which X is control
4310b57cec5SDimitry Andric       // dependent. The following sequence computes the set of blocks
4320b57cec5SDimitry Andric       // which currently have dead terminators that are control
4330b57cec5SDimitry Andric       // dependence sources of a block which is in NewLiveBlocks.
4340b57cec5SDimitry Andric       IDFs.setDefiningBlocks(VNBlocks);
4350b57cec5SDimitry Andric       IDFBlocks.clear();
4360b57cec5SDimitry Andric       IDFs.calculate(IDFBlocks);
4370b57cec5SDimitry Andric 
4380b57cec5SDimitry Andric       // Make a map of BB vs instructions to be hoisted.
4390b57cec5SDimitry Andric       for (unsigned i = 0; i < V.size(); ++i) {
4400b57cec5SDimitry Andric         InValue[V[i]->getParent()].push_back(std::make_pair(VN, V[i]));
4410b57cec5SDimitry Andric       }
4420b57cec5SDimitry Andric       // Insert empty CHI node for this VN. This is used to factor out
4430b57cec5SDimitry Andric       // basic blocks where the ANTIC can potentially change.
444e8d8bef9SDimitry Andric       CHIArg EmptyChi = {VN, nullptr, nullptr};
445e8d8bef9SDimitry Andric       for (auto *IDFBB : IDFBlocks) {
4460b57cec5SDimitry Andric         for (unsigned i = 0; i < V.size(); ++i) {
4470b57cec5SDimitry Andric           // Ignore spurious PDFs.
448e8d8bef9SDimitry Andric           if (DT->properlyDominates(IDFBB, V[i]->getParent())) {
449e8d8bef9SDimitry Andric             OutValue[IDFBB].push_back(EmptyChi);
450e8d8bef9SDimitry Andric             LLVM_DEBUG(dbgs() << "\nInserting a CHI for BB: "
451e8d8bef9SDimitry Andric                               << IDFBB->getName() << ", for Insn: " << *V[i]);
4520b57cec5SDimitry Andric           }
4530b57cec5SDimitry Andric         }
4540b57cec5SDimitry Andric       }
4550b57cec5SDimitry Andric     }
4560b57cec5SDimitry Andric 
4570b57cec5SDimitry Andric     // Insert CHI args at each PDF to iterate on factored graph of
4580b57cec5SDimitry Andric     // control dependence.
4590b57cec5SDimitry Andric     insertCHI(InValue, OutValue);
4600b57cec5SDimitry Andric     // Using the CHI args inserted at each PDF, find fully anticipable values.
4610b57cec5SDimitry Andric     findHoistableCandidates(OutValue, K, HPL);
4620b57cec5SDimitry Andric   }
4630b57cec5SDimitry Andric 
4640b57cec5SDimitry Andric   // Return true when all operands of Instr are available at insertion point
4650b57cec5SDimitry Andric   // HoistPt. When limiting the number of hoisted expressions, one could hoist
4660b57cec5SDimitry Andric   // a load without hoisting its access function. So before hoisting any
4670b57cec5SDimitry Andric   // expression, make sure that all its operands are available at insert point.
4680b57cec5SDimitry Andric   bool allOperandsAvailable(const Instruction *I,
469e8d8bef9SDimitry Andric                             const BasicBlock *HoistPt) const;
470e8d8bef9SDimitry Andric 
471e8d8bef9SDimitry Andric   // Same as allOperandsAvailable with recursive check for GEP operands.
472e8d8bef9SDimitry Andric   bool allGepOperandsAvailable(const Instruction *I,
473e8d8bef9SDimitry Andric                                const BasicBlock *HoistPt) const;
474e8d8bef9SDimitry Andric 
475e8d8bef9SDimitry Andric   // Make all operands of the GEP available.
476e8d8bef9SDimitry Andric   void makeGepsAvailable(Instruction *Repl, BasicBlock *HoistPt,
477e8d8bef9SDimitry Andric                          const SmallVecInsn &InstructionsToHoist,
478e8d8bef9SDimitry Andric                          Instruction *Gep) const;
479e8d8bef9SDimitry Andric 
480e8d8bef9SDimitry Andric   void updateAlignment(Instruction *I, Instruction *Repl);
481e8d8bef9SDimitry Andric 
482e8d8bef9SDimitry Andric   // Remove all the instructions in Candidates and replace their usage with
483e8d8bef9SDimitry Andric   // Repl. Returns the number of instructions removed.
484e8d8bef9SDimitry Andric   unsigned rauw(const SmallVecInsn &Candidates, Instruction *Repl,
485e8d8bef9SDimitry Andric                 MemoryUseOrDef *NewMemAcc);
486e8d8bef9SDimitry Andric 
487e8d8bef9SDimitry Andric   // Replace all Memory PHI usage with NewMemAcc.
488e8d8bef9SDimitry Andric   void raMPHIuw(MemoryUseOrDef *NewMemAcc);
489e8d8bef9SDimitry Andric 
490e8d8bef9SDimitry Andric   // Remove all other instructions and replace them with Repl.
491e8d8bef9SDimitry Andric   unsigned removeAndReplace(const SmallVecInsn &Candidates, Instruction *Repl,
492e8d8bef9SDimitry Andric                             BasicBlock *DestBB, bool MoveAccess);
493e8d8bef9SDimitry Andric 
494e8d8bef9SDimitry Andric   // In the case Repl is a load or a store, we make all their GEPs
495e8d8bef9SDimitry Andric   // available: GEPs are not hoisted by default to avoid the address
496e8d8bef9SDimitry Andric   // computations to be hoisted without the associated load or store.
497e8d8bef9SDimitry Andric   bool makeGepOperandsAvailable(Instruction *Repl, BasicBlock *HoistPt,
498e8d8bef9SDimitry Andric                                 const SmallVecInsn &InstructionsToHoist) const;
499e8d8bef9SDimitry Andric 
500e8d8bef9SDimitry Andric   std::pair<unsigned, unsigned> hoist(HoistingPointList &HPL);
501e8d8bef9SDimitry Andric 
502e8d8bef9SDimitry Andric   // Hoist all expressions. Returns Number of scalars hoisted
503e8d8bef9SDimitry Andric   // and number of non-scalars hoisted.
504e8d8bef9SDimitry Andric   std::pair<unsigned, unsigned> hoistExpressions(Function &F);
505e8d8bef9SDimitry Andric };
506e8d8bef9SDimitry Andric 
507e8d8bef9SDimitry Andric bool GVNHoist::run(Function &F) {
508e8d8bef9SDimitry Andric   NumFuncArgs = F.arg_size();
509e8d8bef9SDimitry Andric   VN.setDomTree(DT);
510e8d8bef9SDimitry Andric   VN.setAliasAnalysis(AA);
511e8d8bef9SDimitry Andric   VN.setMemDep(MD);
512e8d8bef9SDimitry Andric   bool Res = false;
513e8d8bef9SDimitry Andric   // Perform DFS Numbering of instructions.
514e8d8bef9SDimitry Andric   unsigned BBI = 0;
515e8d8bef9SDimitry Andric   for (const BasicBlock *BB : depth_first(&F.getEntryBlock())) {
516e8d8bef9SDimitry Andric     DFSNumber[BB] = ++BBI;
517e8d8bef9SDimitry Andric     unsigned I = 0;
518bdd1243dSDimitry Andric     for (const auto &Inst : *BB)
519e8d8bef9SDimitry Andric       DFSNumber[&Inst] = ++I;
520e8d8bef9SDimitry Andric   }
521e8d8bef9SDimitry Andric 
522e8d8bef9SDimitry Andric   int ChainLength = 0;
523e8d8bef9SDimitry Andric 
524e8d8bef9SDimitry Andric   // FIXME: use lazy evaluation of VN to avoid the fix-point computation.
525e8d8bef9SDimitry Andric   while (true) {
526e8d8bef9SDimitry Andric     if (MaxChainLength != -1 && ++ChainLength >= MaxChainLength)
527e8d8bef9SDimitry Andric       return Res;
528e8d8bef9SDimitry Andric 
529e8d8bef9SDimitry Andric     auto HoistStat = hoistExpressions(F);
530e8d8bef9SDimitry Andric     if (HoistStat.first + HoistStat.second == 0)
531e8d8bef9SDimitry Andric       return Res;
532e8d8bef9SDimitry Andric 
533e8d8bef9SDimitry Andric     if (HoistStat.second > 0)
534e8d8bef9SDimitry Andric       // To address a limitation of the current GVN, we need to rerun the
535e8d8bef9SDimitry Andric       // hoisting after we hoisted loads or stores in order to be able to
536e8d8bef9SDimitry Andric       // hoist all scalars dependent on the hoisted ld/st.
537e8d8bef9SDimitry Andric       VN.clear();
538e8d8bef9SDimitry Andric 
539e8d8bef9SDimitry Andric     Res = true;
540e8d8bef9SDimitry Andric   }
541e8d8bef9SDimitry Andric 
542e8d8bef9SDimitry Andric   return Res;
543e8d8bef9SDimitry Andric }
544e8d8bef9SDimitry Andric 
545e8d8bef9SDimitry Andric unsigned int GVNHoist::rank(const Value *V) const {
546e8d8bef9SDimitry Andric   // Prefer constants to undef to anything else
547e8d8bef9SDimitry Andric   // Undef is a constant, have to check it first.
548e8d8bef9SDimitry Andric   // Prefer smaller constants to constantexprs
549e8d8bef9SDimitry Andric   if (isa<ConstantExpr>(V))
550e8d8bef9SDimitry Andric     return 2;
551e8d8bef9SDimitry Andric   if (isa<UndefValue>(V))
552e8d8bef9SDimitry Andric     return 1;
553e8d8bef9SDimitry Andric   if (isa<Constant>(V))
554e8d8bef9SDimitry Andric     return 0;
555e8d8bef9SDimitry Andric   else if (auto *A = dyn_cast<Argument>(V))
556e8d8bef9SDimitry Andric     return 3 + A->getArgNo();
557e8d8bef9SDimitry Andric 
558e8d8bef9SDimitry Andric   // Need to shift the instruction DFS by number of arguments + 3 to account
559e8d8bef9SDimitry Andric   // for the constant and argument ranking above.
560e8d8bef9SDimitry Andric   auto Result = DFSNumber.lookup(V);
561e8d8bef9SDimitry Andric   if (Result > 0)
562e8d8bef9SDimitry Andric     return 4 + NumFuncArgs + Result;
563e8d8bef9SDimitry Andric   // Unreachable or something else, just return a really large number.
564e8d8bef9SDimitry Andric   return ~0;
565e8d8bef9SDimitry Andric }
566e8d8bef9SDimitry Andric 
567e8d8bef9SDimitry Andric bool GVNHoist::hasEH(const BasicBlock *BB) {
568e8d8bef9SDimitry Andric   auto It = BBSideEffects.find(BB);
569e8d8bef9SDimitry Andric   if (It != BBSideEffects.end())
570e8d8bef9SDimitry Andric     return It->second;
571e8d8bef9SDimitry Andric 
572e8d8bef9SDimitry Andric   if (BB->isEHPad() || BB->hasAddressTaken()) {
573e8d8bef9SDimitry Andric     BBSideEffects[BB] = true;
574e8d8bef9SDimitry Andric     return true;
575e8d8bef9SDimitry Andric   }
576e8d8bef9SDimitry Andric 
577e8d8bef9SDimitry Andric   if (BB->getTerminator()->mayThrow()) {
578e8d8bef9SDimitry Andric     BBSideEffects[BB] = true;
579e8d8bef9SDimitry Andric     return true;
580e8d8bef9SDimitry Andric   }
581e8d8bef9SDimitry Andric 
582e8d8bef9SDimitry Andric   BBSideEffects[BB] = false;
583e8d8bef9SDimitry Andric   return false;
584e8d8bef9SDimitry Andric }
585e8d8bef9SDimitry Andric 
586e8d8bef9SDimitry Andric bool GVNHoist::hasMemoryUse(const Instruction *NewPt, MemoryDef *Def,
587e8d8bef9SDimitry Andric                             const BasicBlock *BB) {
588e8d8bef9SDimitry Andric   const MemorySSA::AccessList *Acc = MSSA->getBlockAccesses(BB);
589e8d8bef9SDimitry Andric   if (!Acc)
590e8d8bef9SDimitry Andric     return false;
591e8d8bef9SDimitry Andric 
592e8d8bef9SDimitry Andric   Instruction *OldPt = Def->getMemoryInst();
593e8d8bef9SDimitry Andric   const BasicBlock *OldBB = OldPt->getParent();
594e8d8bef9SDimitry Andric   const BasicBlock *NewBB = NewPt->getParent();
595e8d8bef9SDimitry Andric   bool ReachedNewPt = false;
596e8d8bef9SDimitry Andric 
597e8d8bef9SDimitry Andric   for (const MemoryAccess &MA : *Acc)
598e8d8bef9SDimitry Andric     if (const MemoryUse *MU = dyn_cast<MemoryUse>(&MA)) {
599e8d8bef9SDimitry Andric       Instruction *Insn = MU->getMemoryInst();
600e8d8bef9SDimitry Andric 
601e8d8bef9SDimitry Andric       // Do not check whether MU aliases Def when MU occurs after OldPt.
602e8d8bef9SDimitry Andric       if (BB == OldBB && firstInBB(OldPt, Insn))
603e8d8bef9SDimitry Andric         break;
604e8d8bef9SDimitry Andric 
605e8d8bef9SDimitry Andric       // Do not check whether MU aliases Def when MU occurs before NewPt.
606e8d8bef9SDimitry Andric       if (BB == NewBB) {
607e8d8bef9SDimitry Andric         if (!ReachedNewPt) {
608e8d8bef9SDimitry Andric           if (firstInBB(Insn, NewPt))
609e8d8bef9SDimitry Andric             continue;
610e8d8bef9SDimitry Andric           ReachedNewPt = true;
611e8d8bef9SDimitry Andric         }
612e8d8bef9SDimitry Andric       }
613e8d8bef9SDimitry Andric       if (MemorySSAUtil::defClobbersUseOrDef(Def, MU, *AA))
614e8d8bef9SDimitry Andric         return true;
615e8d8bef9SDimitry Andric     }
616e8d8bef9SDimitry Andric 
617e8d8bef9SDimitry Andric   return false;
618e8d8bef9SDimitry Andric }
619e8d8bef9SDimitry Andric 
620e8d8bef9SDimitry Andric bool GVNHoist::hasEHhelper(const BasicBlock *BB, const BasicBlock *SrcBB,
621e8d8bef9SDimitry Andric                            int &NBBsOnAllPaths) {
622e8d8bef9SDimitry Andric   // Stop walk once the limit is reached.
623e8d8bef9SDimitry Andric   if (NBBsOnAllPaths == 0)
624e8d8bef9SDimitry Andric     return true;
625e8d8bef9SDimitry Andric 
626e8d8bef9SDimitry Andric   // Impossible to hoist with exceptions on the path.
627e8d8bef9SDimitry Andric   if (hasEH(BB))
628e8d8bef9SDimitry Andric     return true;
629e8d8bef9SDimitry Andric 
630e8d8bef9SDimitry Andric   // No such instruction after HoistBarrier in a basic block was
631e8d8bef9SDimitry Andric   // selected for hoisting so instructions selected within basic block with
632e8d8bef9SDimitry Andric   // a hoist barrier can be hoisted.
633e8d8bef9SDimitry Andric   if ((BB != SrcBB) && HoistBarrier.count(BB))
634e8d8bef9SDimitry Andric     return true;
635e8d8bef9SDimitry Andric 
636e8d8bef9SDimitry Andric   return false;
637e8d8bef9SDimitry Andric }
638e8d8bef9SDimitry Andric 
639e8d8bef9SDimitry Andric bool GVNHoist::hasEHOrLoadsOnPath(const Instruction *NewPt, MemoryDef *Def,
640e8d8bef9SDimitry Andric                                   int &NBBsOnAllPaths) {
641e8d8bef9SDimitry Andric   const BasicBlock *NewBB = NewPt->getParent();
642e8d8bef9SDimitry Andric   const BasicBlock *OldBB = Def->getBlock();
643e8d8bef9SDimitry Andric   assert(DT->dominates(NewBB, OldBB) && "invalid path");
644e8d8bef9SDimitry Andric   assert(DT->dominates(Def->getDefiningAccess()->getBlock(), NewBB) &&
645e8d8bef9SDimitry Andric          "def does not dominate new hoisting point");
646e8d8bef9SDimitry Andric 
647e8d8bef9SDimitry Andric   // Walk all basic blocks reachable in depth-first iteration on the inverse
648e8d8bef9SDimitry Andric   // CFG from OldBB to NewBB. These blocks are all the blocks that may be
649e8d8bef9SDimitry Andric   // executed between the execution of NewBB and OldBB. Hoisting an expression
650e8d8bef9SDimitry Andric   // from OldBB into NewBB has to be safe on all execution paths.
651e8d8bef9SDimitry Andric   for (auto I = idf_begin(OldBB), E = idf_end(OldBB); I != E;) {
652e8d8bef9SDimitry Andric     const BasicBlock *BB = *I;
653e8d8bef9SDimitry Andric     if (BB == NewBB) {
654e8d8bef9SDimitry Andric       // Stop traversal when reaching HoistPt.
655e8d8bef9SDimitry Andric       I.skipChildren();
656e8d8bef9SDimitry Andric       continue;
657e8d8bef9SDimitry Andric     }
658e8d8bef9SDimitry Andric 
659e8d8bef9SDimitry Andric     if (hasEHhelper(BB, OldBB, NBBsOnAllPaths))
660e8d8bef9SDimitry Andric       return true;
661e8d8bef9SDimitry Andric 
662e8d8bef9SDimitry Andric     // Check that we do not move a store past loads.
663e8d8bef9SDimitry Andric     if (hasMemoryUse(NewPt, Def, BB))
664e8d8bef9SDimitry Andric       return true;
665e8d8bef9SDimitry Andric 
666e8d8bef9SDimitry Andric     // -1 is unlimited number of blocks on all paths.
667e8d8bef9SDimitry Andric     if (NBBsOnAllPaths != -1)
668e8d8bef9SDimitry Andric       --NBBsOnAllPaths;
669e8d8bef9SDimitry Andric 
670e8d8bef9SDimitry Andric     ++I;
671e8d8bef9SDimitry Andric   }
672e8d8bef9SDimitry Andric 
673e8d8bef9SDimitry Andric   return false;
674e8d8bef9SDimitry Andric }
675e8d8bef9SDimitry Andric 
676e8d8bef9SDimitry Andric bool GVNHoist::hasEHOnPath(const BasicBlock *HoistPt, const BasicBlock *SrcBB,
677e8d8bef9SDimitry Andric                            int &NBBsOnAllPaths) {
678e8d8bef9SDimitry Andric   assert(DT->dominates(HoistPt, SrcBB) && "Invalid path");
679e8d8bef9SDimitry Andric 
680e8d8bef9SDimitry Andric   // Walk all basic blocks reachable in depth-first iteration on
681e8d8bef9SDimitry Andric   // the inverse CFG from BBInsn to NewHoistPt. These blocks are all the
682e8d8bef9SDimitry Andric   // blocks that may be executed between the execution of NewHoistPt and
683e8d8bef9SDimitry Andric   // BBInsn. Hoisting an expression from BBInsn into NewHoistPt has to be safe
684e8d8bef9SDimitry Andric   // on all execution paths.
685e8d8bef9SDimitry Andric   for (auto I = idf_begin(SrcBB), E = idf_end(SrcBB); I != E;) {
686e8d8bef9SDimitry Andric     const BasicBlock *BB = *I;
687e8d8bef9SDimitry Andric     if (BB == HoistPt) {
688e8d8bef9SDimitry Andric       // Stop traversal when reaching NewHoistPt.
689e8d8bef9SDimitry Andric       I.skipChildren();
690e8d8bef9SDimitry Andric       continue;
691e8d8bef9SDimitry Andric     }
692e8d8bef9SDimitry Andric 
693e8d8bef9SDimitry Andric     if (hasEHhelper(BB, SrcBB, NBBsOnAllPaths))
694e8d8bef9SDimitry Andric       return true;
695e8d8bef9SDimitry Andric 
696e8d8bef9SDimitry Andric     // -1 is unlimited number of blocks on all paths.
697e8d8bef9SDimitry Andric     if (NBBsOnAllPaths != -1)
698e8d8bef9SDimitry Andric       --NBBsOnAllPaths;
699e8d8bef9SDimitry Andric 
700e8d8bef9SDimitry Andric     ++I;
701e8d8bef9SDimitry Andric   }
702e8d8bef9SDimitry Andric 
703e8d8bef9SDimitry Andric   return false;
704e8d8bef9SDimitry Andric }
705e8d8bef9SDimitry Andric 
706e8d8bef9SDimitry Andric bool GVNHoist::safeToHoistLdSt(const Instruction *NewPt,
707e8d8bef9SDimitry Andric                                const Instruction *OldPt, MemoryUseOrDef *U,
708e8d8bef9SDimitry Andric                                GVNHoist::InsKind K, int &NBBsOnAllPaths) {
709e8d8bef9SDimitry Andric   // In place hoisting is safe.
710e8d8bef9SDimitry Andric   if (NewPt == OldPt)
711e8d8bef9SDimitry Andric     return true;
712e8d8bef9SDimitry Andric 
713e8d8bef9SDimitry Andric   const BasicBlock *NewBB = NewPt->getParent();
714e8d8bef9SDimitry Andric   const BasicBlock *OldBB = OldPt->getParent();
715e8d8bef9SDimitry Andric   const BasicBlock *UBB = U->getBlock();
716e8d8bef9SDimitry Andric 
717e8d8bef9SDimitry Andric   // Check for dependences on the Memory SSA.
718e8d8bef9SDimitry Andric   MemoryAccess *D = U->getDefiningAccess();
719e8d8bef9SDimitry Andric   BasicBlock *DBB = D->getBlock();
720e8d8bef9SDimitry Andric   if (DT->properlyDominates(NewBB, DBB))
721e8d8bef9SDimitry Andric     // Cannot move the load or store to NewBB above its definition in DBB.
722e8d8bef9SDimitry Andric     return false;
723e8d8bef9SDimitry Andric 
724e8d8bef9SDimitry Andric   if (NewBB == DBB && !MSSA->isLiveOnEntryDef(D))
725e8d8bef9SDimitry Andric     if (auto *UD = dyn_cast<MemoryUseOrDef>(D))
726e8d8bef9SDimitry Andric       if (!firstInBB(UD->getMemoryInst(), NewPt))
727e8d8bef9SDimitry Andric         // Cannot move the load or store to NewPt above its definition in D.
728e8d8bef9SDimitry Andric         return false;
729e8d8bef9SDimitry Andric 
730e8d8bef9SDimitry Andric   // Check for unsafe hoistings due to side effects.
731e8d8bef9SDimitry Andric   if (K == InsKind::Store) {
732e8d8bef9SDimitry Andric     if (hasEHOrLoadsOnPath(NewPt, cast<MemoryDef>(U), NBBsOnAllPaths))
733e8d8bef9SDimitry Andric       return false;
734e8d8bef9SDimitry Andric   } else if (hasEHOnPath(NewBB, OldBB, NBBsOnAllPaths))
735e8d8bef9SDimitry Andric     return false;
736e8d8bef9SDimitry Andric 
737e8d8bef9SDimitry Andric   if (UBB == NewBB) {
738e8d8bef9SDimitry Andric     if (DT->properlyDominates(DBB, NewBB))
739e8d8bef9SDimitry Andric       return true;
740e8d8bef9SDimitry Andric     assert(UBB == DBB);
741e8d8bef9SDimitry Andric     assert(MSSA->locallyDominates(D, U));
742e8d8bef9SDimitry Andric   }
743e8d8bef9SDimitry Andric 
744e8d8bef9SDimitry Andric   // No side effects: it is safe to hoist.
745e8d8bef9SDimitry Andric   return true;
746e8d8bef9SDimitry Andric }
747e8d8bef9SDimitry Andric 
748e8d8bef9SDimitry Andric bool GVNHoist::valueAnticipable(CHIArgs C, Instruction *TI) const {
749e8d8bef9SDimitry Andric   if (TI->getNumSuccessors() > (unsigned)size(C))
750e8d8bef9SDimitry Andric     return false; // Not enough args in this CHI.
751e8d8bef9SDimitry Andric 
752e8d8bef9SDimitry Andric   for (auto CHI : C) {
753e8d8bef9SDimitry Andric     // Find if all the edges have values flowing out of BB.
754e8d8bef9SDimitry Andric     if (!llvm::is_contained(successors(TI), CHI.Dest))
755e8d8bef9SDimitry Andric       return false;
756e8d8bef9SDimitry Andric   }
757e8d8bef9SDimitry Andric   return true;
758e8d8bef9SDimitry Andric }
759e8d8bef9SDimitry Andric 
760e8d8bef9SDimitry Andric void GVNHoist::checkSafety(CHIArgs C, BasicBlock *BB, GVNHoist::InsKind K,
761e8d8bef9SDimitry Andric                            SmallVectorImpl<CHIArg> &Safe) {
762e8d8bef9SDimitry Andric   int NumBBsOnAllPaths = MaxNumberOfBBSInPath;
76306c3fb27SDimitry Andric   const Instruction *T = BB->getTerminator();
764e8d8bef9SDimitry Andric   for (auto CHI : C) {
765e8d8bef9SDimitry Andric     Instruction *Insn = CHI.I;
766e8d8bef9SDimitry Andric     if (!Insn) // No instruction was inserted in this CHI.
767e8d8bef9SDimitry Andric       continue;
76806c3fb27SDimitry Andric     // If the Terminator is some kind of "exotic terminator" that produces a
76906c3fb27SDimitry Andric     // value (such as InvokeInst, CallBrInst, or CatchSwitchInst) which the CHI
77006c3fb27SDimitry Andric     // uses, it is not safe to hoist the use above the def.
77106c3fb27SDimitry Andric     if (!T->use_empty() && is_contained(Insn->operands(), cast<const Value>(T)))
77206c3fb27SDimitry Andric       continue;
773e8d8bef9SDimitry Andric     if (K == InsKind::Scalar) {
774e8d8bef9SDimitry Andric       if (safeToHoistScalar(BB, Insn->getParent(), NumBBsOnAllPaths))
775e8d8bef9SDimitry Andric         Safe.push_back(CHI);
776e8d8bef9SDimitry Andric     } else {
777e8d8bef9SDimitry Andric       if (MemoryUseOrDef *UD = MSSA->getMemoryAccess(Insn))
778e8d8bef9SDimitry Andric         if (safeToHoistLdSt(T, Insn, UD, K, NumBBsOnAllPaths))
779e8d8bef9SDimitry Andric           Safe.push_back(CHI);
780e8d8bef9SDimitry Andric     }
781e8d8bef9SDimitry Andric   }
782e8d8bef9SDimitry Andric }
783e8d8bef9SDimitry Andric 
784e8d8bef9SDimitry Andric void GVNHoist::fillRenameStack(BasicBlock *BB, InValuesType &ValueBBs,
785e8d8bef9SDimitry Andric                                GVNHoist::RenameStackType &RenameStack) {
786e8d8bef9SDimitry Andric   auto it1 = ValueBBs.find(BB);
787e8d8bef9SDimitry Andric   if (it1 != ValueBBs.end()) {
788e8d8bef9SDimitry Andric     // Iterate in reverse order to keep lower ranked values on the top.
789349cc55cSDimitry Andric     LLVM_DEBUG(dbgs() << "\nVisiting: " << BB->getName()
790349cc55cSDimitry Andric                       << " for pushing instructions on stack";);
791e8d8bef9SDimitry Andric     for (std::pair<VNType, Instruction *> &VI : reverse(it1->second)) {
792e8d8bef9SDimitry Andric       // Get the value of instruction I
793e8d8bef9SDimitry Andric       LLVM_DEBUG(dbgs() << "\nPushing on stack: " << *VI.second);
794e8d8bef9SDimitry Andric       RenameStack[VI.first].push_back(VI.second);
795e8d8bef9SDimitry Andric     }
796e8d8bef9SDimitry Andric   }
797e8d8bef9SDimitry Andric }
798e8d8bef9SDimitry Andric 
799e8d8bef9SDimitry Andric void GVNHoist::fillChiArgs(BasicBlock *BB, OutValuesType &CHIBBs,
800e8d8bef9SDimitry Andric                            GVNHoist::RenameStackType &RenameStack) {
801e8d8bef9SDimitry Andric   // For each *predecessor* (because Post-DOM) of BB check if it has a CHI
802bdd1243dSDimitry Andric   for (auto *Pred : predecessors(BB)) {
803e8d8bef9SDimitry Andric     auto P = CHIBBs.find(Pred);
804e8d8bef9SDimitry Andric     if (P == CHIBBs.end()) {
805e8d8bef9SDimitry Andric       continue;
806e8d8bef9SDimitry Andric     }
807e8d8bef9SDimitry Andric     LLVM_DEBUG(dbgs() << "\nLooking at CHIs in: " << Pred->getName(););
808e8d8bef9SDimitry Andric     // A CHI is found (BB -> Pred is an edge in the CFG)
809e8d8bef9SDimitry Andric     // Pop the stack until Top(V) = Ve.
810e8d8bef9SDimitry Andric     auto &VCHI = P->second;
811e8d8bef9SDimitry Andric     for (auto It = VCHI.begin(), E = VCHI.end(); It != E;) {
812e8d8bef9SDimitry Andric       CHIArg &C = *It;
813e8d8bef9SDimitry Andric       if (!C.Dest) {
814e8d8bef9SDimitry Andric         auto si = RenameStack.find(C.VN);
815e8d8bef9SDimitry Andric         // The Basic Block where CHI is must dominate the value we want to
816e8d8bef9SDimitry Andric         // track in a CHI. In the PDom walk, there can be values in the
817e8d8bef9SDimitry Andric         // stack which are not control dependent e.g., nested loop.
818e8d8bef9SDimitry Andric         if (si != RenameStack.end() && si->second.size() &&
819e8d8bef9SDimitry Andric             DT->properlyDominates(Pred, si->second.back()->getParent())) {
820e8d8bef9SDimitry Andric           C.Dest = BB;                     // Assign the edge
821e8d8bef9SDimitry Andric           C.I = si->second.pop_back_val(); // Assign the argument
822e8d8bef9SDimitry Andric           LLVM_DEBUG(dbgs()
823e8d8bef9SDimitry Andric                      << "\nCHI Inserted in BB: " << C.Dest->getName() << *C.I
824e8d8bef9SDimitry Andric                      << ", VN: " << C.VN.first << ", " << C.VN.second);
825e8d8bef9SDimitry Andric         }
826e8d8bef9SDimitry Andric         // Move to next CHI of a different value
827e8d8bef9SDimitry Andric         It = std::find_if(It, VCHI.end(), [It](CHIArg &A) { return A != *It; });
828e8d8bef9SDimitry Andric       } else
829e8d8bef9SDimitry Andric         ++It;
830e8d8bef9SDimitry Andric     }
831e8d8bef9SDimitry Andric   }
832e8d8bef9SDimitry Andric }
833e8d8bef9SDimitry Andric 
834e8d8bef9SDimitry Andric void GVNHoist::findHoistableCandidates(OutValuesType &CHIBBs,
835e8d8bef9SDimitry Andric                                        GVNHoist::InsKind K,
836e8d8bef9SDimitry Andric                                        HoistingPointList &HPL) {
837e8d8bef9SDimitry Andric   auto cmpVN = [](const CHIArg &A, const CHIArg &B) { return A.VN < B.VN; };
838e8d8bef9SDimitry Andric 
839e8d8bef9SDimitry Andric   // CHIArgs now have the outgoing values, so check for anticipability and
840e8d8bef9SDimitry Andric   // accumulate hoistable candidates in HPL.
841e8d8bef9SDimitry Andric   for (std::pair<BasicBlock *, SmallVector<CHIArg, 2>> &A : CHIBBs) {
842e8d8bef9SDimitry Andric     BasicBlock *BB = A.first;
843e8d8bef9SDimitry Andric     SmallVectorImpl<CHIArg> &CHIs = A.second;
844e8d8bef9SDimitry Andric     // Vector of PHIs contains PHIs for different instructions.
845e8d8bef9SDimitry Andric     // Sort the args according to their VNs, such that identical
846e8d8bef9SDimitry Andric     // instructions are together.
847e8d8bef9SDimitry Andric     llvm::stable_sort(CHIs, cmpVN);
848e8d8bef9SDimitry Andric     auto TI = BB->getTerminator();
849e8d8bef9SDimitry Andric     auto B = CHIs.begin();
850e8d8bef9SDimitry Andric     // [PreIt, PHIIt) form a range of CHIs which have identical VNs.
851e8d8bef9SDimitry Andric     auto PHIIt = llvm::find_if(CHIs, [B](CHIArg &A) { return A != *B; });
852e8d8bef9SDimitry Andric     auto PrevIt = CHIs.begin();
853e8d8bef9SDimitry Andric     while (PrevIt != PHIIt) {
854e8d8bef9SDimitry Andric       // Collect values which satisfy safety checks.
855e8d8bef9SDimitry Andric       SmallVector<CHIArg, 2> Safe;
856e8d8bef9SDimitry Andric       // We check for safety first because there might be multiple values in
857e8d8bef9SDimitry Andric       // the same path, some of which are not safe to be hoisted, but overall
858e8d8bef9SDimitry Andric       // each edge has at least one value which can be hoisted, making the
859e8d8bef9SDimitry Andric       // value anticipable along that path.
860e8d8bef9SDimitry Andric       checkSafety(make_range(PrevIt, PHIIt), BB, K, Safe);
861e8d8bef9SDimitry Andric 
862e8d8bef9SDimitry Andric       // List of safe values should be anticipable at TI.
863e8d8bef9SDimitry Andric       if (valueAnticipable(make_range(Safe.begin(), Safe.end()), TI)) {
864e8d8bef9SDimitry Andric         HPL.push_back({BB, SmallVecInsn()});
865e8d8bef9SDimitry Andric         SmallVecInsn &V = HPL.back().second;
866e8d8bef9SDimitry Andric         for (auto B : Safe)
867e8d8bef9SDimitry Andric           V.push_back(B.I);
868e8d8bef9SDimitry Andric       }
869e8d8bef9SDimitry Andric 
870e8d8bef9SDimitry Andric       // Check other VNs
871e8d8bef9SDimitry Andric       PrevIt = PHIIt;
872e8d8bef9SDimitry Andric       PHIIt = std::find_if(PrevIt, CHIs.end(),
873e8d8bef9SDimitry Andric                            [PrevIt](CHIArg &A) { return A != *PrevIt; });
874e8d8bef9SDimitry Andric     }
875e8d8bef9SDimitry Andric   }
876e8d8bef9SDimitry Andric }
877e8d8bef9SDimitry Andric 
878e8d8bef9SDimitry Andric bool GVNHoist::allOperandsAvailable(const Instruction *I,
8790b57cec5SDimitry Andric                                     const BasicBlock *HoistPt) const {
8800b57cec5SDimitry Andric   for (const Use &Op : I->operands())
8810b57cec5SDimitry Andric     if (const auto *Inst = dyn_cast<Instruction>(&Op))
8820b57cec5SDimitry Andric       if (!DT->dominates(Inst->getParent(), HoistPt))
8830b57cec5SDimitry Andric         return false;
8840b57cec5SDimitry Andric 
8850b57cec5SDimitry Andric   return true;
8860b57cec5SDimitry Andric }
8870b57cec5SDimitry Andric 
888e8d8bef9SDimitry Andric bool GVNHoist::allGepOperandsAvailable(const Instruction *I,
8890b57cec5SDimitry Andric                                        const BasicBlock *HoistPt) const {
8900b57cec5SDimitry Andric   for (const Use &Op : I->operands())
8910b57cec5SDimitry Andric     if (const auto *Inst = dyn_cast<Instruction>(&Op))
8920b57cec5SDimitry Andric       if (!DT->dominates(Inst->getParent(), HoistPt)) {
8930b57cec5SDimitry Andric         if (const GetElementPtrInst *GepOp =
8940b57cec5SDimitry Andric                 dyn_cast<GetElementPtrInst>(Inst)) {
8950b57cec5SDimitry Andric           if (!allGepOperandsAvailable(GepOp, HoistPt))
8960b57cec5SDimitry Andric             return false;
8970b57cec5SDimitry Andric           // Gep is available if all operands of GepOp are available.
8980b57cec5SDimitry Andric         } else {
8990b57cec5SDimitry Andric           // Gep is not available if it has operands other than GEPs that are
9000b57cec5SDimitry Andric           // defined in blocks not dominating HoistPt.
9010b57cec5SDimitry Andric           return false;
9020b57cec5SDimitry Andric         }
9030b57cec5SDimitry Andric       }
9040b57cec5SDimitry Andric   return true;
9050b57cec5SDimitry Andric }
9060b57cec5SDimitry Andric 
907e8d8bef9SDimitry Andric void GVNHoist::makeGepsAvailable(Instruction *Repl, BasicBlock *HoistPt,
9080b57cec5SDimitry Andric                                  const SmallVecInsn &InstructionsToHoist,
9090b57cec5SDimitry Andric                                  Instruction *Gep) const {
910e8d8bef9SDimitry Andric   assert(allGepOperandsAvailable(Gep, HoistPt) && "GEP operands not available");
9110b57cec5SDimitry Andric 
9120b57cec5SDimitry Andric   Instruction *ClonedGep = Gep->clone();
9130b57cec5SDimitry Andric   for (unsigned i = 0, e = Gep->getNumOperands(); i != e; ++i)
9140b57cec5SDimitry Andric     if (Instruction *Op = dyn_cast<Instruction>(Gep->getOperand(i))) {
9150b57cec5SDimitry Andric       // Check whether the operand is already available.
9160b57cec5SDimitry Andric       if (DT->dominates(Op->getParent(), HoistPt))
9170b57cec5SDimitry Andric         continue;
9180b57cec5SDimitry Andric 
9190b57cec5SDimitry Andric       // As a GEP can refer to other GEPs, recursively make all the operands
9200b57cec5SDimitry Andric       // of this GEP available at HoistPt.
9210b57cec5SDimitry Andric       if (GetElementPtrInst *GepOp = dyn_cast<GetElementPtrInst>(Op))
9220b57cec5SDimitry Andric         makeGepsAvailable(ClonedGep, HoistPt, InstructionsToHoist, GepOp);
9230b57cec5SDimitry Andric     }
9240b57cec5SDimitry Andric 
9250b57cec5SDimitry Andric   // Copy Gep and replace its uses in Repl with ClonedGep.
9260b57cec5SDimitry Andric   ClonedGep->insertBefore(HoistPt->getTerminator());
9270b57cec5SDimitry Andric 
9280b57cec5SDimitry Andric   // Conservatively discard any optimization hints, they may differ on the
9290b57cec5SDimitry Andric   // other paths.
9300b57cec5SDimitry Andric   ClonedGep->dropUnknownNonDebugMetadata();
9310b57cec5SDimitry Andric 
9320b57cec5SDimitry Andric   // If we have optimization hints which agree with each other along different
9330b57cec5SDimitry Andric   // paths, preserve them.
9340b57cec5SDimitry Andric   for (const Instruction *OtherInst : InstructionsToHoist) {
9350b57cec5SDimitry Andric     const GetElementPtrInst *OtherGep;
9360b57cec5SDimitry Andric     if (auto *OtherLd = dyn_cast<LoadInst>(OtherInst))
9370b57cec5SDimitry Andric       OtherGep = cast<GetElementPtrInst>(OtherLd->getPointerOperand());
9380b57cec5SDimitry Andric     else
9390b57cec5SDimitry Andric       OtherGep = cast<GetElementPtrInst>(
9400b57cec5SDimitry Andric           cast<StoreInst>(OtherInst)->getPointerOperand());
9410b57cec5SDimitry Andric     ClonedGep->andIRFlags(OtherGep);
942*0fca6ea1SDimitry Andric 
943*0fca6ea1SDimitry Andric     // Merge debug locations of GEPs, because the hoisted GEP replaces those
944*0fca6ea1SDimitry Andric     // in branches. When cloning, ClonedGep preserves the debug location of
945*0fca6ea1SDimitry Andric     // Gepd, so Gep is skipped to avoid merging it twice.
946*0fca6ea1SDimitry Andric     if (OtherGep != Gep) {
947*0fca6ea1SDimitry Andric       ClonedGep->applyMergedLocation(ClonedGep->getDebugLoc(),
948*0fca6ea1SDimitry Andric                                      OtherGep->getDebugLoc());
949*0fca6ea1SDimitry Andric     }
9500b57cec5SDimitry Andric   }
9510b57cec5SDimitry Andric 
9520b57cec5SDimitry Andric   // Replace uses of Gep with ClonedGep in Repl.
9530b57cec5SDimitry Andric   Repl->replaceUsesOfWith(Gep, ClonedGep);
9540b57cec5SDimitry Andric }
9550b57cec5SDimitry Andric 
956e8d8bef9SDimitry Andric void GVNHoist::updateAlignment(Instruction *I, Instruction *Repl) {
9570b57cec5SDimitry Andric   if (auto *ReplacementLoad = dyn_cast<LoadInst>(Repl)) {
9585ffd83dbSDimitry Andric     ReplacementLoad->setAlignment(
9595ffd83dbSDimitry Andric         std::min(ReplacementLoad->getAlign(), cast<LoadInst>(I)->getAlign()));
9600b57cec5SDimitry Andric     ++NumLoadsRemoved;
9610b57cec5SDimitry Andric   } else if (auto *ReplacementStore = dyn_cast<StoreInst>(Repl)) {
962e8d8bef9SDimitry Andric     ReplacementStore->setAlignment(
963e8d8bef9SDimitry Andric         std::min(ReplacementStore->getAlign(), cast<StoreInst>(I)->getAlign()));
9640b57cec5SDimitry Andric     ++NumStoresRemoved;
9650b57cec5SDimitry Andric   } else if (auto *ReplacementAlloca = dyn_cast<AllocaInst>(Repl)) {
966e8d8bef9SDimitry Andric     ReplacementAlloca->setAlignment(std::max(ReplacementAlloca->getAlign(),
967e8d8bef9SDimitry Andric                                              cast<AllocaInst>(I)->getAlign()));
9680b57cec5SDimitry Andric   } else if (isa<CallInst>(Repl)) {
9690b57cec5SDimitry Andric     ++NumCallsRemoved;
9700b57cec5SDimitry Andric   }
9710b57cec5SDimitry Andric }
9720b57cec5SDimitry Andric 
973e8d8bef9SDimitry Andric unsigned GVNHoist::rauw(const SmallVecInsn &Candidates, Instruction *Repl,
9740b57cec5SDimitry Andric                         MemoryUseOrDef *NewMemAcc) {
9750b57cec5SDimitry Andric   unsigned NR = 0;
9760b57cec5SDimitry Andric   for (Instruction *I : Candidates) {
9770b57cec5SDimitry Andric     if (I != Repl) {
9780b57cec5SDimitry Andric       ++NR;
9790b57cec5SDimitry Andric       updateAlignment(I, Repl);
9800b57cec5SDimitry Andric       if (NewMemAcc) {
9810b57cec5SDimitry Andric         // Update the uses of the old MSSA access with NewMemAcc.
9820b57cec5SDimitry Andric         MemoryAccess *OldMA = MSSA->getMemoryAccess(I);
9830b57cec5SDimitry Andric         OldMA->replaceAllUsesWith(NewMemAcc);
9840b57cec5SDimitry Andric         MSSAUpdater->removeMemoryAccess(OldMA);
9850b57cec5SDimitry Andric       }
9860b57cec5SDimitry Andric 
987*0fca6ea1SDimitry Andric       combineMetadataForCSE(Repl, I, true);
9880b57cec5SDimitry Andric       Repl->andIRFlags(I);
9890b57cec5SDimitry Andric       I->replaceAllUsesWith(Repl);
9900b57cec5SDimitry Andric       // Also invalidate the Alias Analysis cache.
9910b57cec5SDimitry Andric       MD->removeInstruction(I);
9920b57cec5SDimitry Andric       I->eraseFromParent();
9930b57cec5SDimitry Andric     }
9940b57cec5SDimitry Andric   }
9950b57cec5SDimitry Andric   return NR;
9960b57cec5SDimitry Andric }
9970b57cec5SDimitry Andric 
998e8d8bef9SDimitry Andric void GVNHoist::raMPHIuw(MemoryUseOrDef *NewMemAcc) {
9990b57cec5SDimitry Andric   SmallPtrSet<MemoryPhi *, 4> UsePhis;
10000b57cec5SDimitry Andric   for (User *U : NewMemAcc->users())
10010b57cec5SDimitry Andric     if (MemoryPhi *Phi = dyn_cast<MemoryPhi>(U))
10020b57cec5SDimitry Andric       UsePhis.insert(Phi);
10030b57cec5SDimitry Andric 
10040b57cec5SDimitry Andric   for (MemoryPhi *Phi : UsePhis) {
10050b57cec5SDimitry Andric     auto In = Phi->incoming_values();
10060b57cec5SDimitry Andric     if (llvm::all_of(In, [&](Use &U) { return U == NewMemAcc; })) {
10070b57cec5SDimitry Andric       Phi->replaceAllUsesWith(NewMemAcc);
10080b57cec5SDimitry Andric       MSSAUpdater->removeMemoryAccess(Phi);
10090b57cec5SDimitry Andric     }
10100b57cec5SDimitry Andric   }
10110b57cec5SDimitry Andric }
10120b57cec5SDimitry Andric 
1013e8d8bef9SDimitry Andric unsigned GVNHoist::removeAndReplace(const SmallVecInsn &Candidates,
1014e8d8bef9SDimitry Andric                                     Instruction *Repl, BasicBlock *DestBB,
1015e8d8bef9SDimitry Andric                                     bool MoveAccess) {
10160b57cec5SDimitry Andric   MemoryUseOrDef *NewMemAcc = MSSA->getMemoryAccess(Repl);
10170b57cec5SDimitry Andric   if (MoveAccess && NewMemAcc) {
10180b57cec5SDimitry Andric     // The definition of this ld/st will not change: ld/st hoisting is
10190b57cec5SDimitry Andric     // legal when the ld/st is not moved past its current definition.
1020e8d8bef9SDimitry Andric     MSSAUpdater->moveToPlace(NewMemAcc, DestBB, MemorySSA::BeforeTerminator);
10210b57cec5SDimitry Andric   }
10220b57cec5SDimitry Andric 
10230b57cec5SDimitry Andric   // Replace all other instructions with Repl with memory access NewMemAcc.
10240b57cec5SDimitry Andric   unsigned NR = rauw(Candidates, Repl, NewMemAcc);
10250b57cec5SDimitry Andric 
10260b57cec5SDimitry Andric   // Remove MemorySSA phi nodes with the same arguments.
10270b57cec5SDimitry Andric   if (NewMemAcc)
10280b57cec5SDimitry Andric     raMPHIuw(NewMemAcc);
10290b57cec5SDimitry Andric   return NR;
10300b57cec5SDimitry Andric }
10310b57cec5SDimitry Andric 
1032e8d8bef9SDimitry Andric bool GVNHoist::makeGepOperandsAvailable(
1033e8d8bef9SDimitry Andric     Instruction *Repl, BasicBlock *HoistPt,
10340b57cec5SDimitry Andric     const SmallVecInsn &InstructionsToHoist) const {
10350b57cec5SDimitry Andric   // Check whether the GEP of a ld/st can be synthesized at HoistPt.
10360b57cec5SDimitry Andric   GetElementPtrInst *Gep = nullptr;
10370b57cec5SDimitry Andric   Instruction *Val = nullptr;
10380b57cec5SDimitry Andric   if (auto *Ld = dyn_cast<LoadInst>(Repl)) {
10390b57cec5SDimitry Andric     Gep = dyn_cast<GetElementPtrInst>(Ld->getPointerOperand());
10400b57cec5SDimitry Andric   } else if (auto *St = dyn_cast<StoreInst>(Repl)) {
10410b57cec5SDimitry Andric     Gep = dyn_cast<GetElementPtrInst>(St->getPointerOperand());
10420b57cec5SDimitry Andric     Val = dyn_cast<Instruction>(St->getValueOperand());
10430b57cec5SDimitry Andric     // Check that the stored value is available.
10440b57cec5SDimitry Andric     if (Val) {
10450b57cec5SDimitry Andric       if (isa<GetElementPtrInst>(Val)) {
10460b57cec5SDimitry Andric         // Check whether we can compute the GEP at HoistPt.
10470b57cec5SDimitry Andric         if (!allGepOperandsAvailable(Val, HoistPt))
10480b57cec5SDimitry Andric           return false;
10490b57cec5SDimitry Andric       } else if (!DT->dominates(Val->getParent(), HoistPt))
10500b57cec5SDimitry Andric         return false;
10510b57cec5SDimitry Andric     }
10520b57cec5SDimitry Andric   }
10530b57cec5SDimitry Andric 
10540b57cec5SDimitry Andric   // Check whether we can compute the Gep at HoistPt.
10550b57cec5SDimitry Andric   if (!Gep || !allGepOperandsAvailable(Gep, HoistPt))
10560b57cec5SDimitry Andric     return false;
10570b57cec5SDimitry Andric 
10580b57cec5SDimitry Andric   makeGepsAvailable(Repl, HoistPt, InstructionsToHoist, Gep);
10590b57cec5SDimitry Andric 
10600b57cec5SDimitry Andric   if (Val && isa<GetElementPtrInst>(Val))
10610b57cec5SDimitry Andric     makeGepsAvailable(Repl, HoistPt, InstructionsToHoist, Val);
10620b57cec5SDimitry Andric 
10630b57cec5SDimitry Andric   return true;
10640b57cec5SDimitry Andric }
10650b57cec5SDimitry Andric 
1066e8d8bef9SDimitry Andric std::pair<unsigned, unsigned> GVNHoist::hoist(HoistingPointList &HPL) {
10670b57cec5SDimitry Andric   unsigned NI = 0, NL = 0, NS = 0, NC = 0, NR = 0;
10680b57cec5SDimitry Andric   for (const HoistingPointInfo &HP : HPL) {
10690b57cec5SDimitry Andric     // Find out whether we already have one of the instructions in HoistPt,
10700b57cec5SDimitry Andric     // in which case we do not have to move it.
10710b57cec5SDimitry Andric     BasicBlock *DestBB = HP.first;
10720b57cec5SDimitry Andric     const SmallVecInsn &InstructionsToHoist = HP.second;
10730b57cec5SDimitry Andric     Instruction *Repl = nullptr;
10740b57cec5SDimitry Andric     for (Instruction *I : InstructionsToHoist)
10750b57cec5SDimitry Andric       if (I->getParent() == DestBB)
10760b57cec5SDimitry Andric         // If there are two instructions in HoistPt to be hoisted in place:
10770b57cec5SDimitry Andric         // update Repl to be the first one, such that we can rename the uses
10780b57cec5SDimitry Andric         // of the second based on the first.
10790b57cec5SDimitry Andric         if (!Repl || firstInBB(I, Repl))
10800b57cec5SDimitry Andric           Repl = I;
10810b57cec5SDimitry Andric 
10820b57cec5SDimitry Andric     // Keep track of whether we moved the instruction so we know whether we
10830b57cec5SDimitry Andric     // should move the MemoryAccess.
10840b57cec5SDimitry Andric     bool MoveAccess = true;
10850b57cec5SDimitry Andric     if (Repl) {
10860b57cec5SDimitry Andric       // Repl is already in HoistPt: it remains in place.
10870b57cec5SDimitry Andric       assert(allOperandsAvailable(Repl, DestBB) &&
10880b57cec5SDimitry Andric              "instruction depends on operands that are not available");
10890b57cec5SDimitry Andric       MoveAccess = false;
10900b57cec5SDimitry Andric     } else {
10910b57cec5SDimitry Andric       // When we do not find Repl in HoistPt, select the first in the list
10920b57cec5SDimitry Andric       // and move it to HoistPt.
10930b57cec5SDimitry Andric       Repl = InstructionsToHoist.front();
10940b57cec5SDimitry Andric 
10950b57cec5SDimitry Andric       // We can move Repl in HoistPt only when all operands are available.
10960b57cec5SDimitry Andric       // The order in which hoistings are done may influence the availability
10970b57cec5SDimitry Andric       // of operands.
10980b57cec5SDimitry Andric       if (!allOperandsAvailable(Repl, DestBB)) {
10990b57cec5SDimitry Andric         // When HoistingGeps there is nothing more we can do to make the
11000b57cec5SDimitry Andric         // operands available: just continue.
11010b57cec5SDimitry Andric         if (HoistingGeps)
11020b57cec5SDimitry Andric           continue;
11030b57cec5SDimitry Andric 
11040b57cec5SDimitry Andric         // When not HoistingGeps we need to copy the GEPs.
11050b57cec5SDimitry Andric         if (!makeGepOperandsAvailable(Repl, DestBB, InstructionsToHoist))
11060b57cec5SDimitry Andric           continue;
11070b57cec5SDimitry Andric       }
11080b57cec5SDimitry Andric 
11090b57cec5SDimitry Andric       // Move the instruction at the end of HoistPt.
11100b57cec5SDimitry Andric       Instruction *Last = DestBB->getTerminator();
11110b57cec5SDimitry Andric       MD->removeInstruction(Repl);
11120b57cec5SDimitry Andric       Repl->moveBefore(Last);
11130b57cec5SDimitry Andric 
11140b57cec5SDimitry Andric       DFSNumber[Repl] = DFSNumber[Last]++;
11150b57cec5SDimitry Andric     }
11160b57cec5SDimitry Andric 
111781ad6265SDimitry Andric     // Drop debug location as per debug info update guide.
111881ad6265SDimitry Andric     Repl->dropLocation();
11190b57cec5SDimitry Andric     NR += removeAndReplace(InstructionsToHoist, Repl, DestBB, MoveAccess);
11200b57cec5SDimitry Andric 
11210b57cec5SDimitry Andric     if (isa<LoadInst>(Repl))
11220b57cec5SDimitry Andric       ++NL;
11230b57cec5SDimitry Andric     else if (isa<StoreInst>(Repl))
11240b57cec5SDimitry Andric       ++NS;
11250b57cec5SDimitry Andric     else if (isa<CallInst>(Repl))
11260b57cec5SDimitry Andric       ++NC;
11270b57cec5SDimitry Andric     else // Scalar
11280b57cec5SDimitry Andric       ++NI;
11290b57cec5SDimitry Andric   }
11300b57cec5SDimitry Andric 
1131480093f4SDimitry Andric   if (MSSA && VerifyMemorySSA)
1132480093f4SDimitry Andric     MSSA->verifyMemorySSA();
1133480093f4SDimitry Andric 
11340b57cec5SDimitry Andric   NumHoisted += NL + NS + NC + NI;
11350b57cec5SDimitry Andric   NumRemoved += NR;
11360b57cec5SDimitry Andric   NumLoadsHoisted += NL;
11370b57cec5SDimitry Andric   NumStoresHoisted += NS;
11380b57cec5SDimitry Andric   NumCallsHoisted += NC;
11390b57cec5SDimitry Andric   return {NI, NL + NC + NS};
11400b57cec5SDimitry Andric }
11410b57cec5SDimitry Andric 
1142e8d8bef9SDimitry Andric std::pair<unsigned, unsigned> GVNHoist::hoistExpressions(Function &F) {
11430b57cec5SDimitry Andric   InsnInfo II;
11440b57cec5SDimitry Andric   LoadInfo LI;
11450b57cec5SDimitry Andric   StoreInfo SI;
11460b57cec5SDimitry Andric   CallInfo CI;
11470b57cec5SDimitry Andric   for (BasicBlock *BB : depth_first(&F.getEntryBlock())) {
11480b57cec5SDimitry Andric     int InstructionNb = 0;
11490b57cec5SDimitry Andric     for (Instruction &I1 : *BB) {
11500b57cec5SDimitry Andric       // If I1 cannot guarantee progress, subsequent instructions
11510b57cec5SDimitry Andric       // in BB cannot be hoisted anyways.
11520b57cec5SDimitry Andric       if (!isGuaranteedToTransferExecutionToSuccessor(&I1)) {
11530b57cec5SDimitry Andric         HoistBarrier.insert(BB);
11540b57cec5SDimitry Andric         break;
11550b57cec5SDimitry Andric       }
11560b57cec5SDimitry Andric       // Only hoist the first instructions in BB up to MaxDepthInBB. Hoisting
11570b57cec5SDimitry Andric       // deeper may increase the register pressure and compilation time.
11580b57cec5SDimitry Andric       if (MaxDepthInBB != -1 && InstructionNb++ >= MaxDepthInBB)
11590b57cec5SDimitry Andric         break;
11600b57cec5SDimitry Andric 
11610b57cec5SDimitry Andric       // Do not value number terminator instructions.
11620b57cec5SDimitry Andric       if (I1.isTerminator())
11630b57cec5SDimitry Andric         break;
11640b57cec5SDimitry Andric 
11650b57cec5SDimitry Andric       if (auto *Load = dyn_cast<LoadInst>(&I1))
11660b57cec5SDimitry Andric         LI.insert(Load, VN);
11670b57cec5SDimitry Andric       else if (auto *Store = dyn_cast<StoreInst>(&I1))
11680b57cec5SDimitry Andric         SI.insert(Store, VN);
11690b57cec5SDimitry Andric       else if (auto *Call = dyn_cast<CallInst>(&I1)) {
11700b57cec5SDimitry Andric         if (auto *Intr = dyn_cast<IntrinsicInst>(Call)) {
11710b57cec5SDimitry Andric           if (isa<DbgInfoIntrinsic>(Intr) ||
11720b57cec5SDimitry Andric               Intr->getIntrinsicID() == Intrinsic::assume ||
11730b57cec5SDimitry Andric               Intr->getIntrinsicID() == Intrinsic::sideeffect)
11740b57cec5SDimitry Andric             continue;
11750b57cec5SDimitry Andric         }
11760b57cec5SDimitry Andric         if (Call->mayHaveSideEffects())
11770b57cec5SDimitry Andric           break;
11780b57cec5SDimitry Andric 
11790b57cec5SDimitry Andric         if (Call->isConvergent())
11800b57cec5SDimitry Andric           break;
11810b57cec5SDimitry Andric 
11820b57cec5SDimitry Andric         CI.insert(Call, VN);
11830b57cec5SDimitry Andric       } else if (HoistingGeps || !isa<GetElementPtrInst>(&I1))
11840b57cec5SDimitry Andric         // Do not hoist scalars past calls that may write to memory because
11850b57cec5SDimitry Andric         // that could result in spills later. geps are handled separately.
11860b57cec5SDimitry Andric         // TODO: We can relax this for targets like AArch64 as they have more
11870b57cec5SDimitry Andric         // registers than X86.
11880b57cec5SDimitry Andric         II.insert(&I1, VN);
11890b57cec5SDimitry Andric     }
11900b57cec5SDimitry Andric   }
11910b57cec5SDimitry Andric 
11920b57cec5SDimitry Andric   HoistingPointList HPL;
11930b57cec5SDimitry Andric   computeInsertionPoints(II.getVNTable(), HPL, InsKind::Scalar);
11940b57cec5SDimitry Andric   computeInsertionPoints(LI.getVNTable(), HPL, InsKind::Load);
11950b57cec5SDimitry Andric   computeInsertionPoints(SI.getVNTable(), HPL, InsKind::Store);
11960b57cec5SDimitry Andric   computeInsertionPoints(CI.getScalarVNTable(), HPL, InsKind::Scalar);
11970b57cec5SDimitry Andric   computeInsertionPoints(CI.getLoadVNTable(), HPL, InsKind::Load);
11980b57cec5SDimitry Andric   computeInsertionPoints(CI.getStoreVNTable(), HPL, InsKind::Store);
11990b57cec5SDimitry Andric   return hoist(HPL);
12000b57cec5SDimitry Andric }
12010b57cec5SDimitry Andric 
12020b57cec5SDimitry Andric } // end namespace llvm
12030b57cec5SDimitry Andric 
12040b57cec5SDimitry Andric PreservedAnalyses GVNHoistPass::run(Function &F, FunctionAnalysisManager &AM) {
12050b57cec5SDimitry Andric   DominatorTree &DT = AM.getResult<DominatorTreeAnalysis>(F);
12060b57cec5SDimitry Andric   PostDominatorTree &PDT = AM.getResult<PostDominatorTreeAnalysis>(F);
12070b57cec5SDimitry Andric   AliasAnalysis &AA = AM.getResult<AAManager>(F);
12080b57cec5SDimitry Andric   MemoryDependenceResults &MD = AM.getResult<MemoryDependenceAnalysis>(F);
12090b57cec5SDimitry Andric   MemorySSA &MSSA = AM.getResult<MemorySSAAnalysis>(F).getMSSA();
12100b57cec5SDimitry Andric   GVNHoist G(&DT, &PDT, &AA, &MD, &MSSA);
12110b57cec5SDimitry Andric   if (!G.run(F))
12120b57cec5SDimitry Andric     return PreservedAnalyses::all();
12130b57cec5SDimitry Andric 
12140b57cec5SDimitry Andric   PreservedAnalyses PA;
12150b57cec5SDimitry Andric   PA.preserve<DominatorTreeAnalysis>();
12160b57cec5SDimitry Andric   PA.preserve<MemorySSAAnalysis>();
12170b57cec5SDimitry Andric   return PA;
12180b57cec5SDimitry Andric }
1219