xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/Scalar/EarlyCSE.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- EarlyCSE.cpp - Simple and fast CSE pass ----------------------------===//
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 performs a simple dominator tree walk that eliminates trivially
100b57cec5SDimitry Andric // redundant instructions.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/EarlyCSE.h"
150b57cec5SDimitry Andric #include "llvm/ADT/DenseMapInfo.h"
160b57cec5SDimitry Andric #include "llvm/ADT/Hashing.h"
170b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
180b57cec5SDimitry Andric #include "llvm/ADT/ScopedHashTable.h"
190b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
200b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
210b57cec5SDimitry Andric #include "llvm/Analysis/AssumptionCache.h"
220b57cec5SDimitry Andric #include "llvm/Analysis/GlobalsModRef.h"
230b57cec5SDimitry Andric #include "llvm/Analysis/GuardUtils.h"
240b57cec5SDimitry Andric #include "llvm/Analysis/InstructionSimplify.h"
250b57cec5SDimitry Andric #include "llvm/Analysis/MemorySSA.h"
260b57cec5SDimitry Andric #include "llvm/Analysis/MemorySSAUpdater.h"
270b57cec5SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h"
280b57cec5SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h"
290b57cec5SDimitry Andric #include "llvm/Analysis/ValueTracking.h"
300b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h"
310b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
320b57cec5SDimitry Andric #include "llvm/IR/Dominators.h"
330b57cec5SDimitry Andric #include "llvm/IR/Function.h"
340b57cec5SDimitry Andric #include "llvm/IR/InstrTypes.h"
350b57cec5SDimitry Andric #include "llvm/IR/Instruction.h"
360b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
370b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
380b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h"
390b57cec5SDimitry Andric #include "llvm/IR/PassManager.h"
400b57cec5SDimitry Andric #include "llvm/IR/PatternMatch.h"
410b57cec5SDimitry Andric #include "llvm/IR/Type.h"
420b57cec5SDimitry Andric #include "llvm/IR/Value.h"
43480093f4SDimitry Andric #include "llvm/InitializePasses.h"
440b57cec5SDimitry Andric #include "llvm/Pass.h"
450b57cec5SDimitry Andric #include "llvm/Support/Allocator.h"
460b57cec5SDimitry Andric #include "llvm/Support/AtomicOrdering.h"
470b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
480b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
490b57cec5SDimitry Andric #include "llvm/Support/DebugCounter.h"
500b57cec5SDimitry Andric #include "llvm/Support/RecyclingAllocator.h"
510b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
520b57cec5SDimitry Andric #include "llvm/Transforms/Scalar.h"
535ffd83dbSDimitry Andric #include "llvm/Transforms/Utils/AssumeBundleBuilder.h"
54480093f4SDimitry Andric #include "llvm/Transforms/Utils/Local.h"
550b57cec5SDimitry Andric #include <cassert>
560b57cec5SDimitry Andric #include <deque>
570b57cec5SDimitry Andric #include <memory>
580b57cec5SDimitry Andric #include <utility>
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric using namespace llvm;
610b57cec5SDimitry Andric using namespace llvm::PatternMatch;
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric #define DEBUG_TYPE "early-cse"
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric STATISTIC(NumSimplify, "Number of instructions simplified or DCE'd");
660b57cec5SDimitry Andric STATISTIC(NumCSE,      "Number of instructions CSE'd");
670b57cec5SDimitry Andric STATISTIC(NumCSECVP,   "Number of compare instructions CVP'd");
680b57cec5SDimitry Andric STATISTIC(NumCSELoad,  "Number of load instructions CSE'd");
690b57cec5SDimitry Andric STATISTIC(NumCSECall,  "Number of call instructions CSE'd");
705f757f3fSDimitry Andric STATISTIC(NumCSEGEP, "Number of GEP instructions CSE'd");
710b57cec5SDimitry Andric STATISTIC(NumDSE,      "Number of trivial dead stores removed");
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric DEBUG_COUNTER(CSECounter, "early-cse",
740b57cec5SDimitry Andric               "Controls which instructions are removed");
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric static cl::opt<unsigned> EarlyCSEMssaOptCap(
770b57cec5SDimitry Andric     "earlycse-mssa-optimization-cap", cl::init(500), cl::Hidden,
780b57cec5SDimitry Andric     cl::desc("Enable imprecision in EarlyCSE in pathological cases, in exchange "
790b57cec5SDimitry Andric              "for faster compile. Caps the MemorySSA clobbering calls."));
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric static cl::opt<bool> EarlyCSEDebugHash(
820b57cec5SDimitry Andric     "earlycse-debug-hash", cl::init(false), cl::Hidden,
830b57cec5SDimitry Andric     cl::desc("Perform extra assertion checking to verify that SimpleValue's hash "
840b57cec5SDimitry Andric              "function is well-behaved w.r.t. its isEqual predicate"));
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
870b57cec5SDimitry Andric // SimpleValue
880b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric namespace {
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric /// Struct representing the available values in the scoped hash table.
930b57cec5SDimitry Andric struct SimpleValue {
940b57cec5SDimitry Andric   Instruction *Inst;
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   SimpleValue(Instruction *I) : Inst(I) {
970b57cec5SDimitry Andric     assert((isSentinel() || canHandle(I)) && "Inst can't be handled!");
980b57cec5SDimitry Andric   }
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric   bool isSentinel() const {
1010b57cec5SDimitry Andric     return Inst == DenseMapInfo<Instruction *>::getEmptyKey() ||
1020b57cec5SDimitry Andric            Inst == DenseMapInfo<Instruction *>::getTombstoneKey();
1030b57cec5SDimitry Andric   }
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   static bool canHandle(Instruction *Inst) {
1060b57cec5SDimitry Andric     // This can only handle non-void readnone functions.
107fe6060f1SDimitry Andric     // Also handled are constrained intrinsic that look like the types
108fe6060f1SDimitry Andric     // of instruction handled below (UnaryOperator, etc.).
109fe6060f1SDimitry Andric     if (CallInst *CI = dyn_cast<CallInst>(Inst)) {
110fe6060f1SDimitry Andric       if (Function *F = CI->getCalledFunction()) {
111fe6060f1SDimitry Andric         switch ((Intrinsic::ID)F->getIntrinsicID()) {
112fe6060f1SDimitry Andric         case Intrinsic::experimental_constrained_fadd:
113fe6060f1SDimitry Andric         case Intrinsic::experimental_constrained_fsub:
114fe6060f1SDimitry Andric         case Intrinsic::experimental_constrained_fmul:
115fe6060f1SDimitry Andric         case Intrinsic::experimental_constrained_fdiv:
116fe6060f1SDimitry Andric         case Intrinsic::experimental_constrained_frem:
117fe6060f1SDimitry Andric         case Intrinsic::experimental_constrained_fptosi:
118fe6060f1SDimitry Andric         case Intrinsic::experimental_constrained_sitofp:
119fe6060f1SDimitry Andric         case Intrinsic::experimental_constrained_fptoui:
120fe6060f1SDimitry Andric         case Intrinsic::experimental_constrained_uitofp:
121fe6060f1SDimitry Andric         case Intrinsic::experimental_constrained_fcmp:
122fe6060f1SDimitry Andric         case Intrinsic::experimental_constrained_fcmps: {
123fe6060f1SDimitry Andric           auto *CFP = cast<ConstrainedFPIntrinsic>(CI);
124bdd1243dSDimitry Andric           if (CFP->getExceptionBehavior() &&
125bdd1243dSDimitry Andric               CFP->getExceptionBehavior() == fp::ebStrict)
126bdd1243dSDimitry Andric             return false;
127bdd1243dSDimitry Andric           // Since we CSE across function calls we must not allow
128bdd1243dSDimitry Andric           // the rounding mode to change.
129bdd1243dSDimitry Andric           if (CFP->getRoundingMode() &&
130bdd1243dSDimitry Andric               CFP->getRoundingMode() == RoundingMode::Dynamic)
131bdd1243dSDimitry Andric             return false;
132bdd1243dSDimitry Andric           return true;
133fe6060f1SDimitry Andric         }
134fe6060f1SDimitry Andric         }
135fe6060f1SDimitry Andric       }
136bdd1243dSDimitry Andric       return CI->doesNotAccessMemory() && !CI->getType()->isVoidTy() &&
137bdd1243dSDimitry Andric              // FIXME: Currently the calls which may access the thread id may
138bdd1243dSDimitry Andric              // be considered as not accessing the memory. But this is
139bdd1243dSDimitry Andric              // problematic for coroutines, since coroutines may resume in a
140bdd1243dSDimitry Andric              // different thread. So we disable the optimization here for the
141bdd1243dSDimitry Andric              // correctness. However, it may block many other correct
142bdd1243dSDimitry Andric              // optimizations. Revert this one when we detect the memory
143bdd1243dSDimitry Andric              // accessing kind more precisely.
144bdd1243dSDimitry Andric              !CI->getFunction()->isPresplitCoroutine();
145fe6060f1SDimitry Andric     }
1468bcb0991SDimitry Andric     return isa<CastInst>(Inst) || isa<UnaryOperator>(Inst) ||
1475f757f3fSDimitry Andric            isa<BinaryOperator>(Inst) || isa<CmpInst>(Inst) ||
1485f757f3fSDimitry Andric            isa<SelectInst>(Inst) || isa<ExtractElementInst>(Inst) ||
1495f757f3fSDimitry Andric            isa<InsertElementInst>(Inst) || isa<ShuffleVectorInst>(Inst) ||
1505f757f3fSDimitry Andric            isa<ExtractValueInst>(Inst) || isa<InsertValueInst>(Inst) ||
1515f757f3fSDimitry Andric            isa<FreezeInst>(Inst);
1520b57cec5SDimitry Andric   }
1530b57cec5SDimitry Andric };
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric } // end anonymous namespace
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric namespace llvm {
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric template <> struct DenseMapInfo<SimpleValue> {
1600b57cec5SDimitry Andric   static inline SimpleValue getEmptyKey() {
1610b57cec5SDimitry Andric     return DenseMapInfo<Instruction *>::getEmptyKey();
1620b57cec5SDimitry Andric   }
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric   static inline SimpleValue getTombstoneKey() {
1650b57cec5SDimitry Andric     return DenseMapInfo<Instruction *>::getTombstoneKey();
1660b57cec5SDimitry Andric   }
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   static unsigned getHashValue(SimpleValue Val);
1690b57cec5SDimitry Andric   static bool isEqual(SimpleValue LHS, SimpleValue RHS);
1700b57cec5SDimitry Andric };
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric } // end namespace llvm
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric /// Match a 'select' including an optional 'not's of the condition.
1750b57cec5SDimitry Andric static bool matchSelectWithOptionalNotCond(Value *V, Value *&Cond, Value *&A,
1760b57cec5SDimitry Andric                                            Value *&B,
1770b57cec5SDimitry Andric                                            SelectPatternFlavor &Flavor) {
1780b57cec5SDimitry Andric   // Return false if V is not even a select.
1790b57cec5SDimitry Andric   if (!match(V, m_Select(m_Value(Cond), m_Value(A), m_Value(B))))
1800b57cec5SDimitry Andric     return false;
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric   // Look through a 'not' of the condition operand by swapping A/B.
1830b57cec5SDimitry Andric   Value *CondNot;
1840b57cec5SDimitry Andric   if (match(Cond, m_Not(m_Value(CondNot)))) {
1850b57cec5SDimitry Andric     Cond = CondNot;
1860b57cec5SDimitry Andric     std::swap(A, B);
1870b57cec5SDimitry Andric   }
1880b57cec5SDimitry Andric 
189e8d8bef9SDimitry Andric   // Match canonical forms of min/max. We are not using ValueTracking's
190e39dad62SDimitry Andric   // more powerful matchSelectPattern() because it may rely on instruction flags
191e39dad62SDimitry Andric   // such as "nsw". That would be incompatible with the current hashing
192e39dad62SDimitry Andric   // mechanism that may remove flags to increase the likelihood of CSE.
193e39dad62SDimitry Andric 
1940b57cec5SDimitry Andric   Flavor = SPF_UNKNOWN;
195e39dad62SDimitry Andric   CmpInst::Predicate Pred;
196e39dad62SDimitry Andric 
197e39dad62SDimitry Andric   if (!match(Cond, m_ICmp(Pred, m_Specific(A), m_Specific(B)))) {
198e39dad62SDimitry Andric     // Check for commuted variants of min/max by swapping predicate.
199e39dad62SDimitry Andric     // If we do not match the standard or commuted patterns, this is not a
200e39dad62SDimitry Andric     // recognized form of min/max, but it is still a select, so return true.
201e39dad62SDimitry Andric     if (!match(Cond, m_ICmp(Pred, m_Specific(B), m_Specific(A))))
202e39dad62SDimitry Andric       return true;
203e39dad62SDimitry Andric     Pred = ICmpInst::getSwappedPredicate(Pred);
204e39dad62SDimitry Andric   }
205e39dad62SDimitry Andric 
206e39dad62SDimitry Andric   switch (Pred) {
207e39dad62SDimitry Andric   case CmpInst::ICMP_UGT: Flavor = SPF_UMAX; break;
208e39dad62SDimitry Andric   case CmpInst::ICMP_ULT: Flavor = SPF_UMIN; break;
209e39dad62SDimitry Andric   case CmpInst::ICMP_SGT: Flavor = SPF_SMAX; break;
210e39dad62SDimitry Andric   case CmpInst::ICMP_SLT: Flavor = SPF_SMIN; break;
211e8d8bef9SDimitry Andric   // Non-strict inequalities.
212e8d8bef9SDimitry Andric   case CmpInst::ICMP_ULE: Flavor = SPF_UMIN; break;
213e8d8bef9SDimitry Andric   case CmpInst::ICMP_UGE: Flavor = SPF_UMAX; break;
214e8d8bef9SDimitry Andric   case CmpInst::ICMP_SLE: Flavor = SPF_SMIN; break;
215e8d8bef9SDimitry Andric   case CmpInst::ICMP_SGE: Flavor = SPF_SMAX; break;
216e39dad62SDimitry Andric   default: break;
217e39dad62SDimitry Andric   }
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric   return true;
2200b57cec5SDimitry Andric }
2210b57cec5SDimitry Andric 
22206c3fb27SDimitry Andric static unsigned hashCallInst(CallInst *CI) {
22306c3fb27SDimitry Andric   // Don't CSE convergent calls in different basic blocks, because they
22406c3fb27SDimitry Andric   // implicitly depend on the set of threads that is currently executing.
22506c3fb27SDimitry Andric   if (CI->isConvergent()) {
22606c3fb27SDimitry Andric     return hash_combine(
22706c3fb27SDimitry Andric         CI->getOpcode(), CI->getParent(),
22806c3fb27SDimitry Andric         hash_combine_range(CI->value_op_begin(), CI->value_op_end()));
22906c3fb27SDimitry Andric   }
23006c3fb27SDimitry Andric   return hash_combine(
23106c3fb27SDimitry Andric       CI->getOpcode(),
23206c3fb27SDimitry Andric       hash_combine_range(CI->value_op_begin(), CI->value_op_end()));
23306c3fb27SDimitry Andric }
23406c3fb27SDimitry Andric 
2350b57cec5SDimitry Andric static unsigned getHashValueImpl(SimpleValue Val) {
2360b57cec5SDimitry Andric   Instruction *Inst = Val.Inst;
2370b57cec5SDimitry Andric   // Hash in all of the operands as pointers.
2380b57cec5SDimitry Andric   if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(Inst)) {
2390b57cec5SDimitry Andric     Value *LHS = BinOp->getOperand(0);
2400b57cec5SDimitry Andric     Value *RHS = BinOp->getOperand(1);
2410b57cec5SDimitry Andric     if (BinOp->isCommutative() && BinOp->getOperand(0) > BinOp->getOperand(1))
2420b57cec5SDimitry Andric       std::swap(LHS, RHS);
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric     return hash_combine(BinOp->getOpcode(), LHS, RHS);
2450b57cec5SDimitry Andric   }
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric   if (CmpInst *CI = dyn_cast<CmpInst>(Inst)) {
2480b57cec5SDimitry Andric     // Compares can be commuted by swapping the comparands and
2490b57cec5SDimitry Andric     // updating the predicate.  Choose the form that has the
2500b57cec5SDimitry Andric     // comparands in sorted order, or in the case of a tie, the
2510b57cec5SDimitry Andric     // one with the lower predicate.
2520b57cec5SDimitry Andric     Value *LHS = CI->getOperand(0);
2530b57cec5SDimitry Andric     Value *RHS = CI->getOperand(1);
2540b57cec5SDimitry Andric     CmpInst::Predicate Pred = CI->getPredicate();
2550b57cec5SDimitry Andric     CmpInst::Predicate SwappedPred = CI->getSwappedPredicate();
2560b57cec5SDimitry Andric     if (std::tie(LHS, Pred) > std::tie(RHS, SwappedPred)) {
2570b57cec5SDimitry Andric       std::swap(LHS, RHS);
2580b57cec5SDimitry Andric       Pred = SwappedPred;
2590b57cec5SDimitry Andric     }
2600b57cec5SDimitry Andric     return hash_combine(Inst->getOpcode(), Pred, LHS, RHS);
2610b57cec5SDimitry Andric   }
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric   // Hash general selects to allow matching commuted true/false operands.
2640b57cec5SDimitry Andric   SelectPatternFlavor SPF;
2650b57cec5SDimitry Andric   Value *Cond, *A, *B;
2660b57cec5SDimitry Andric   if (matchSelectWithOptionalNotCond(Inst, Cond, A, B, SPF)) {
267e8d8bef9SDimitry Andric     // Hash min/max (cmp + select) to allow for commuted operands.
2680b57cec5SDimitry Andric     // Min/max may also have non-canonical compare predicate (eg, the compare for
2690b57cec5SDimitry Andric     // smin may use 'sgt' rather than 'slt'), and non-canonical operands in the
2700b57cec5SDimitry Andric     // compare.
2710b57cec5SDimitry Andric     // TODO: We should also detect FP min/max.
2720b57cec5SDimitry Andric     if (SPF == SPF_SMIN || SPF == SPF_SMAX ||
2730b57cec5SDimitry Andric         SPF == SPF_UMIN || SPF == SPF_UMAX) {
2740b57cec5SDimitry Andric       if (A > B)
2750b57cec5SDimitry Andric         std::swap(A, B);
2760b57cec5SDimitry Andric       return hash_combine(Inst->getOpcode(), SPF, A, B);
2770b57cec5SDimitry Andric     }
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric     // Hash general selects to allow matching commuted true/false operands.
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric     // If we do not have a compare as the condition, just hash in the condition.
2820b57cec5SDimitry Andric     CmpInst::Predicate Pred;
2830b57cec5SDimitry Andric     Value *X, *Y;
2840b57cec5SDimitry Andric     if (!match(Cond, m_Cmp(Pred, m_Value(X), m_Value(Y))))
2850b57cec5SDimitry Andric       return hash_combine(Inst->getOpcode(), Cond, A, B);
2860b57cec5SDimitry Andric 
2870b57cec5SDimitry Andric     // Similar to cmp normalization (above) - canonicalize the predicate value:
2880b57cec5SDimitry Andric     // select (icmp Pred, X, Y), A, B --> select (icmp InvPred, X, Y), B, A
2890b57cec5SDimitry Andric     if (CmpInst::getInversePredicate(Pred) < Pred) {
2900b57cec5SDimitry Andric       Pred = CmpInst::getInversePredicate(Pred);
2910b57cec5SDimitry Andric       std::swap(A, B);
2920b57cec5SDimitry Andric     }
2930b57cec5SDimitry Andric     return hash_combine(Inst->getOpcode(), Pred, X, Y, A, B);
2940b57cec5SDimitry Andric   }
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric   if (CastInst *CI = dyn_cast<CastInst>(Inst))
2970b57cec5SDimitry Andric     return hash_combine(CI->getOpcode(), CI->getType(), CI->getOperand(0));
2980b57cec5SDimitry Andric 
2995ffd83dbSDimitry Andric   if (FreezeInst *FI = dyn_cast<FreezeInst>(Inst))
3005ffd83dbSDimitry Andric     return hash_combine(FI->getOpcode(), FI->getOperand(0));
3015ffd83dbSDimitry Andric 
3020b57cec5SDimitry Andric   if (const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(Inst))
3030b57cec5SDimitry Andric     return hash_combine(EVI->getOpcode(), EVI->getOperand(0),
3040b57cec5SDimitry Andric                         hash_combine_range(EVI->idx_begin(), EVI->idx_end()));
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric   if (const InsertValueInst *IVI = dyn_cast<InsertValueInst>(Inst))
3070b57cec5SDimitry Andric     return hash_combine(IVI->getOpcode(), IVI->getOperand(0),
3080b57cec5SDimitry Andric                         IVI->getOperand(1),
3090b57cec5SDimitry Andric                         hash_combine_range(IVI->idx_begin(), IVI->idx_end()));
3100b57cec5SDimitry Andric 
3115f757f3fSDimitry Andric   assert((isa<CallInst>(Inst) || isa<ExtractElementInst>(Inst) ||
3125f757f3fSDimitry Andric           isa<InsertElementInst>(Inst) || isa<ShuffleVectorInst>(Inst) ||
3135f757f3fSDimitry Andric           isa<UnaryOperator>(Inst) || isa<FreezeInst>(Inst)) &&
3140b57cec5SDimitry Andric          "Invalid/unknown instruction");
3150b57cec5SDimitry Andric 
316e8d8bef9SDimitry Andric   // Handle intrinsics with commutative operands.
317e8d8bef9SDimitry Andric   auto *II = dyn_cast<IntrinsicInst>(Inst);
3185f757f3fSDimitry Andric   if (II && II->isCommutative() && II->arg_size() >= 2) {
319e8d8bef9SDimitry Andric     Value *LHS = II->getArgOperand(0), *RHS = II->getArgOperand(1);
320e8d8bef9SDimitry Andric     if (LHS > RHS)
321e8d8bef9SDimitry Andric       std::swap(LHS, RHS);
3225f757f3fSDimitry Andric     return hash_combine(
3235f757f3fSDimitry Andric         II->getOpcode(), LHS, RHS,
3245f757f3fSDimitry Andric         hash_combine_range(II->value_op_begin() + 2, II->value_op_end()));
325e8d8bef9SDimitry Andric   }
326e8d8bef9SDimitry Andric 
327fe6060f1SDimitry Andric   // gc.relocate is 'special' call: its second and third operands are
328fe6060f1SDimitry Andric   // not real values, but indices into statepoint's argument list.
329fe6060f1SDimitry Andric   // Get values they point to.
330fe6060f1SDimitry Andric   if (const GCRelocateInst *GCR = dyn_cast<GCRelocateInst>(Inst))
331fe6060f1SDimitry Andric     return hash_combine(GCR->getOpcode(), GCR->getOperand(0),
332fe6060f1SDimitry Andric                         GCR->getBasePtr(), GCR->getDerivedPtr());
333fe6060f1SDimitry Andric 
33406c3fb27SDimitry Andric   // Don't CSE convergent calls in different basic blocks, because they
33506c3fb27SDimitry Andric   // implicitly depend on the set of threads that is currently executing.
33606c3fb27SDimitry Andric   if (CallInst *CI = dyn_cast<CallInst>(Inst))
33706c3fb27SDimitry Andric     return hashCallInst(CI);
33806c3fb27SDimitry Andric 
3390b57cec5SDimitry Andric   // Mix in the opcode.
3400b57cec5SDimitry Andric   return hash_combine(
3410b57cec5SDimitry Andric       Inst->getOpcode(),
3420b57cec5SDimitry Andric       hash_combine_range(Inst->value_op_begin(), Inst->value_op_end()));
3430b57cec5SDimitry Andric }
3440b57cec5SDimitry Andric 
3450b57cec5SDimitry Andric unsigned DenseMapInfo<SimpleValue>::getHashValue(SimpleValue Val) {
3460b57cec5SDimitry Andric #ifndef NDEBUG
3470b57cec5SDimitry Andric   // If -earlycse-debug-hash was specified, return a constant -- this
3480b57cec5SDimitry Andric   // will force all hashing to collide, so we'll exhaustively search
3490b57cec5SDimitry Andric   // the table for a match, and the assertion in isEqual will fire if
3500b57cec5SDimitry Andric   // there's a bug causing equal keys to hash differently.
3510b57cec5SDimitry Andric   if (EarlyCSEDebugHash)
3520b57cec5SDimitry Andric     return 0;
3530b57cec5SDimitry Andric #endif
3540b57cec5SDimitry Andric   return getHashValueImpl(Val);
3550b57cec5SDimitry Andric }
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric static bool isEqualImpl(SimpleValue LHS, SimpleValue RHS) {
3580b57cec5SDimitry Andric   Instruction *LHSI = LHS.Inst, *RHSI = RHS.Inst;
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric   if (LHS.isSentinel() || RHS.isSentinel())
3610b57cec5SDimitry Andric     return LHSI == RHSI;
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric   if (LHSI->getOpcode() != RHSI->getOpcode())
3640b57cec5SDimitry Andric     return false;
36506c3fb27SDimitry Andric   if (LHSI->isIdenticalToWhenDefined(RHSI)) {
36606c3fb27SDimitry Andric     // Convergent calls implicitly depend on the set of threads that is
36706c3fb27SDimitry Andric     // currently executing, so conservatively return false if they are in
36806c3fb27SDimitry Andric     // different basic blocks.
36906c3fb27SDimitry Andric     if (CallInst *CI = dyn_cast<CallInst>(LHSI);
37006c3fb27SDimitry Andric         CI && CI->isConvergent() && LHSI->getParent() != RHSI->getParent())
37106c3fb27SDimitry Andric       return false;
37206c3fb27SDimitry Andric 
3730b57cec5SDimitry Andric     return true;
37406c3fb27SDimitry Andric   }
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric   // If we're not strictly identical, we still might be a commutable instruction
3770b57cec5SDimitry Andric   if (BinaryOperator *LHSBinOp = dyn_cast<BinaryOperator>(LHSI)) {
3780b57cec5SDimitry Andric     if (!LHSBinOp->isCommutative())
3790b57cec5SDimitry Andric       return false;
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric     assert(isa<BinaryOperator>(RHSI) &&
3820b57cec5SDimitry Andric            "same opcode, but different instruction type?");
3830b57cec5SDimitry Andric     BinaryOperator *RHSBinOp = cast<BinaryOperator>(RHSI);
3840b57cec5SDimitry Andric 
3850b57cec5SDimitry Andric     // Commuted equality
3860b57cec5SDimitry Andric     return LHSBinOp->getOperand(0) == RHSBinOp->getOperand(1) &&
3870b57cec5SDimitry Andric            LHSBinOp->getOperand(1) == RHSBinOp->getOperand(0);
3880b57cec5SDimitry Andric   }
3890b57cec5SDimitry Andric   if (CmpInst *LHSCmp = dyn_cast<CmpInst>(LHSI)) {
3900b57cec5SDimitry Andric     assert(isa<CmpInst>(RHSI) &&
3910b57cec5SDimitry Andric            "same opcode, but different instruction type?");
3920b57cec5SDimitry Andric     CmpInst *RHSCmp = cast<CmpInst>(RHSI);
3930b57cec5SDimitry Andric     // Commuted equality
3940b57cec5SDimitry Andric     return LHSCmp->getOperand(0) == RHSCmp->getOperand(1) &&
3950b57cec5SDimitry Andric            LHSCmp->getOperand(1) == RHSCmp->getOperand(0) &&
3960b57cec5SDimitry Andric            LHSCmp->getSwappedPredicate() == RHSCmp->getPredicate();
3970b57cec5SDimitry Andric   }
3980b57cec5SDimitry Andric 
399e8d8bef9SDimitry Andric   auto *LII = dyn_cast<IntrinsicInst>(LHSI);
400e8d8bef9SDimitry Andric   auto *RII = dyn_cast<IntrinsicInst>(RHSI);
401e8d8bef9SDimitry Andric   if (LII && RII && LII->getIntrinsicID() == RII->getIntrinsicID() &&
4025f757f3fSDimitry Andric       LII->isCommutative() && LII->arg_size() >= 2) {
403e8d8bef9SDimitry Andric     return LII->getArgOperand(0) == RII->getArgOperand(1) &&
4045f757f3fSDimitry Andric            LII->getArgOperand(1) == RII->getArgOperand(0) &&
4055f757f3fSDimitry Andric            std::equal(LII->arg_begin() + 2, LII->arg_end(),
4065f757f3fSDimitry Andric                       RII->arg_begin() + 2, RII->arg_end());
407e8d8bef9SDimitry Andric   }
408e8d8bef9SDimitry Andric 
409fe6060f1SDimitry Andric   // See comment above in `getHashValue()`.
410fe6060f1SDimitry Andric   if (const GCRelocateInst *GCR1 = dyn_cast<GCRelocateInst>(LHSI))
411fe6060f1SDimitry Andric     if (const GCRelocateInst *GCR2 = dyn_cast<GCRelocateInst>(RHSI))
412fe6060f1SDimitry Andric       return GCR1->getOperand(0) == GCR2->getOperand(0) &&
413fe6060f1SDimitry Andric              GCR1->getBasePtr() == GCR2->getBasePtr() &&
414fe6060f1SDimitry Andric              GCR1->getDerivedPtr() == GCR2->getDerivedPtr();
415fe6060f1SDimitry Andric 
416e8d8bef9SDimitry Andric   // Min/max can occur with commuted operands, non-canonical predicates,
4170b57cec5SDimitry Andric   // and/or non-canonical operands.
4180b57cec5SDimitry Andric   // Selects can be non-trivially equivalent via inverted conditions and swaps.
4190b57cec5SDimitry Andric   SelectPatternFlavor LSPF, RSPF;
4200b57cec5SDimitry Andric   Value *CondL, *CondR, *LHSA, *RHSA, *LHSB, *RHSB;
4210b57cec5SDimitry Andric   if (matchSelectWithOptionalNotCond(LHSI, CondL, LHSA, LHSB, LSPF) &&
4220b57cec5SDimitry Andric       matchSelectWithOptionalNotCond(RHSI, CondR, RHSA, RHSB, RSPF)) {
4230b57cec5SDimitry Andric     if (LSPF == RSPF) {
4240b57cec5SDimitry Andric       // TODO: We should also detect FP min/max.
4250b57cec5SDimitry Andric       if (LSPF == SPF_SMIN || LSPF == SPF_SMAX ||
4260b57cec5SDimitry Andric           LSPF == SPF_UMIN || LSPF == SPF_UMAX)
4270b57cec5SDimitry Andric         return ((LHSA == RHSA && LHSB == RHSB) ||
4280b57cec5SDimitry Andric                 (LHSA == RHSB && LHSB == RHSA));
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric       // select Cond, A, B <--> select not(Cond), B, A
4310b57cec5SDimitry Andric       if (CondL == CondR && LHSA == RHSA && LHSB == RHSB)
4320b57cec5SDimitry Andric         return true;
4330b57cec5SDimitry Andric     }
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric     // If the true/false operands are swapped and the conditions are compares
4360b57cec5SDimitry Andric     // with inverted predicates, the selects are equal:
4370b57cec5SDimitry Andric     // select (icmp Pred, X, Y), A, B <--> select (icmp InvPred, X, Y), B, A
4380b57cec5SDimitry Andric     //
4390b57cec5SDimitry Andric     // This also handles patterns with a double-negation in the sense of not +
4400b57cec5SDimitry Andric     // inverse, because we looked through a 'not' in the matching function and
4410b57cec5SDimitry Andric     // swapped A/B:
4420b57cec5SDimitry Andric     // select (cmp Pred, X, Y), A, B <--> select (not (cmp InvPred, X, Y)), B, A
4430b57cec5SDimitry Andric     //
4440b57cec5SDimitry Andric     // This intentionally does NOT handle patterns with a double-negation in
4450b57cec5SDimitry Andric     // the sense of not + not, because doing so could result in values
4460b57cec5SDimitry Andric     // comparing
447e8d8bef9SDimitry Andric     // as equal that hash differently in the min/max cases like:
4480b57cec5SDimitry Andric     // select (cmp slt, X, Y), X, Y <--> select (not (not (cmp slt, X, Y))), X, Y
4490b57cec5SDimitry Andric     //   ^ hashes as min                  ^ would not hash as min
4500b57cec5SDimitry Andric     // In the context of the EarlyCSE pass, however, such cases never reach
4510b57cec5SDimitry Andric     // this code, as we simplify the double-negation before hashing the second
4520b57cec5SDimitry Andric     // select (and so still succeed at CSEing them).
4530b57cec5SDimitry Andric     if (LHSA == RHSB && LHSB == RHSA) {
4540b57cec5SDimitry Andric       CmpInst::Predicate PredL, PredR;
4550b57cec5SDimitry Andric       Value *X, *Y;
4560b57cec5SDimitry Andric       if (match(CondL, m_Cmp(PredL, m_Value(X), m_Value(Y))) &&
4570b57cec5SDimitry Andric           match(CondR, m_Cmp(PredR, m_Specific(X), m_Specific(Y))) &&
4580b57cec5SDimitry Andric           CmpInst::getInversePredicate(PredL) == PredR)
4590b57cec5SDimitry Andric         return true;
4600b57cec5SDimitry Andric     }
4610b57cec5SDimitry Andric   }
4620b57cec5SDimitry Andric 
4630b57cec5SDimitry Andric   return false;
4640b57cec5SDimitry Andric }
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric bool DenseMapInfo<SimpleValue>::isEqual(SimpleValue LHS, SimpleValue RHS) {
4670b57cec5SDimitry Andric   // These comparisons are nontrivial, so assert that equality implies
4680b57cec5SDimitry Andric   // hash equality (DenseMap demands this as an invariant).
4690b57cec5SDimitry Andric   bool Result = isEqualImpl(LHS, RHS);
4700b57cec5SDimitry Andric   assert(!Result || (LHS.isSentinel() && LHS.Inst == RHS.Inst) ||
4710b57cec5SDimitry Andric          getHashValueImpl(LHS) == getHashValueImpl(RHS));
4720b57cec5SDimitry Andric   return Result;
4730b57cec5SDimitry Andric }
4740b57cec5SDimitry Andric 
4750b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
4760b57cec5SDimitry Andric // CallValue
4770b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
4780b57cec5SDimitry Andric 
4790b57cec5SDimitry Andric namespace {
4800b57cec5SDimitry Andric 
4810b57cec5SDimitry Andric /// Struct representing the available call values in the scoped hash
4820b57cec5SDimitry Andric /// table.
4830b57cec5SDimitry Andric struct CallValue {
4840b57cec5SDimitry Andric   Instruction *Inst;
4850b57cec5SDimitry Andric 
4860b57cec5SDimitry Andric   CallValue(Instruction *I) : Inst(I) {
4870b57cec5SDimitry Andric     assert((isSentinel() || canHandle(I)) && "Inst can't be handled!");
4880b57cec5SDimitry Andric   }
4890b57cec5SDimitry Andric 
4900b57cec5SDimitry Andric   bool isSentinel() const {
4910b57cec5SDimitry Andric     return Inst == DenseMapInfo<Instruction *>::getEmptyKey() ||
4920b57cec5SDimitry Andric            Inst == DenseMapInfo<Instruction *>::getTombstoneKey();
4930b57cec5SDimitry Andric   }
4940b57cec5SDimitry Andric 
4950b57cec5SDimitry Andric   static bool canHandle(Instruction *Inst) {
4960b57cec5SDimitry Andric     // Don't value number anything that returns void.
4970b57cec5SDimitry Andric     if (Inst->getType()->isVoidTy())
4980b57cec5SDimitry Andric       return false;
4990b57cec5SDimitry Andric 
5000b57cec5SDimitry Andric     CallInst *CI = dyn_cast<CallInst>(Inst);
501bdd1243dSDimitry Andric     if (!CI || !CI->onlyReadsMemory() ||
502bdd1243dSDimitry Andric         // FIXME: Currently the calls which may access the thread id may
503bdd1243dSDimitry Andric         // be considered as not accessing the memory. But this is
504bdd1243dSDimitry Andric         // problematic for coroutines, since coroutines may resume in a
505bdd1243dSDimitry Andric         // different thread. So we disable the optimization here for the
506bdd1243dSDimitry Andric         // correctness. However, it may block many other correct
507bdd1243dSDimitry Andric         // optimizations. Revert this one when we detect the memory
508bdd1243dSDimitry Andric         // accessing kind more precisely.
509bdd1243dSDimitry Andric         CI->getFunction()->isPresplitCoroutine())
5100b57cec5SDimitry Andric       return false;
5110b57cec5SDimitry Andric     return true;
5120b57cec5SDimitry Andric   }
5130b57cec5SDimitry Andric };
5140b57cec5SDimitry Andric 
5150b57cec5SDimitry Andric } // end anonymous namespace
5160b57cec5SDimitry Andric 
5170b57cec5SDimitry Andric namespace llvm {
5180b57cec5SDimitry Andric 
5190b57cec5SDimitry Andric template <> struct DenseMapInfo<CallValue> {
5200b57cec5SDimitry Andric   static inline CallValue getEmptyKey() {
5210b57cec5SDimitry Andric     return DenseMapInfo<Instruction *>::getEmptyKey();
5220b57cec5SDimitry Andric   }
5230b57cec5SDimitry Andric 
5240b57cec5SDimitry Andric   static inline CallValue getTombstoneKey() {
5250b57cec5SDimitry Andric     return DenseMapInfo<Instruction *>::getTombstoneKey();
5260b57cec5SDimitry Andric   }
5270b57cec5SDimitry Andric 
5280b57cec5SDimitry Andric   static unsigned getHashValue(CallValue Val);
5290b57cec5SDimitry Andric   static bool isEqual(CallValue LHS, CallValue RHS);
5300b57cec5SDimitry Andric };
5310b57cec5SDimitry Andric 
5320b57cec5SDimitry Andric } // end namespace llvm
5330b57cec5SDimitry Andric 
5340b57cec5SDimitry Andric unsigned DenseMapInfo<CallValue>::getHashValue(CallValue Val) {
5350b57cec5SDimitry Andric   Instruction *Inst = Val.Inst;
5365ffd83dbSDimitry Andric 
5370b57cec5SDimitry Andric   // Hash all of the operands as pointers and mix in the opcode.
53806c3fb27SDimitry Andric   return hashCallInst(cast<CallInst>(Inst));
5390b57cec5SDimitry Andric }
5400b57cec5SDimitry Andric 
5410b57cec5SDimitry Andric bool DenseMapInfo<CallValue>::isEqual(CallValue LHS, CallValue RHS) {
5420b57cec5SDimitry Andric   if (LHS.isSentinel() || RHS.isSentinel())
54306c3fb27SDimitry Andric     return LHS.Inst == RHS.Inst;
54406c3fb27SDimitry Andric 
54506c3fb27SDimitry Andric   CallInst *LHSI = cast<CallInst>(LHS.Inst);
54606c3fb27SDimitry Andric   CallInst *RHSI = cast<CallInst>(RHS.Inst);
54706c3fb27SDimitry Andric 
54806c3fb27SDimitry Andric   // Convergent calls implicitly depend on the set of threads that is
54906c3fb27SDimitry Andric   // currently executing, so conservatively return false if they are in
55006c3fb27SDimitry Andric   // different basic blocks.
55106c3fb27SDimitry Andric   if (LHSI->isConvergent() && LHSI->getParent() != RHSI->getParent())
55206c3fb27SDimitry Andric     return false;
5535ffd83dbSDimitry Andric 
5540b57cec5SDimitry Andric   return LHSI->isIdenticalTo(RHSI);
5550b57cec5SDimitry Andric }
5560b57cec5SDimitry Andric 
5570b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
5585f757f3fSDimitry Andric // GEPValue
5595f757f3fSDimitry Andric //===----------------------------------------------------------------------===//
5605f757f3fSDimitry Andric 
5615f757f3fSDimitry Andric namespace {
5625f757f3fSDimitry Andric 
5635f757f3fSDimitry Andric struct GEPValue {
5645f757f3fSDimitry Andric   Instruction *Inst;
5655f757f3fSDimitry Andric   std::optional<int64_t> ConstantOffset;
5665f757f3fSDimitry Andric 
5675f757f3fSDimitry Andric   GEPValue(Instruction *I) : Inst(I) {
5685f757f3fSDimitry Andric     assert((isSentinel() || canHandle(I)) && "Inst can't be handled!");
5695f757f3fSDimitry Andric   }
5705f757f3fSDimitry Andric 
5715f757f3fSDimitry Andric   GEPValue(Instruction *I, std::optional<int64_t> ConstantOffset)
5725f757f3fSDimitry Andric       : Inst(I), ConstantOffset(ConstantOffset) {
5735f757f3fSDimitry Andric     assert((isSentinel() || canHandle(I)) && "Inst can't be handled!");
5745f757f3fSDimitry Andric   }
5755f757f3fSDimitry Andric 
5765f757f3fSDimitry Andric   bool isSentinel() const {
5775f757f3fSDimitry Andric     return Inst == DenseMapInfo<Instruction *>::getEmptyKey() ||
5785f757f3fSDimitry Andric            Inst == DenseMapInfo<Instruction *>::getTombstoneKey();
5795f757f3fSDimitry Andric   }
5805f757f3fSDimitry Andric 
5815f757f3fSDimitry Andric   static bool canHandle(Instruction *Inst) {
5825f757f3fSDimitry Andric     return isa<GetElementPtrInst>(Inst);
5835f757f3fSDimitry Andric   }
5845f757f3fSDimitry Andric };
5855f757f3fSDimitry Andric 
5865f757f3fSDimitry Andric } // namespace
5875f757f3fSDimitry Andric 
5885f757f3fSDimitry Andric namespace llvm {
5895f757f3fSDimitry Andric 
5905f757f3fSDimitry Andric template <> struct DenseMapInfo<GEPValue> {
5915f757f3fSDimitry Andric   static inline GEPValue getEmptyKey() {
5925f757f3fSDimitry Andric     return DenseMapInfo<Instruction *>::getEmptyKey();
5935f757f3fSDimitry Andric   }
5945f757f3fSDimitry Andric 
5955f757f3fSDimitry Andric   static inline GEPValue getTombstoneKey() {
5965f757f3fSDimitry Andric     return DenseMapInfo<Instruction *>::getTombstoneKey();
5975f757f3fSDimitry Andric   }
5985f757f3fSDimitry Andric 
5995f757f3fSDimitry Andric   static unsigned getHashValue(const GEPValue &Val);
6005f757f3fSDimitry Andric   static bool isEqual(const GEPValue &LHS, const GEPValue &RHS);
6015f757f3fSDimitry Andric };
6025f757f3fSDimitry Andric 
6035f757f3fSDimitry Andric } // end namespace llvm
6045f757f3fSDimitry Andric 
6055f757f3fSDimitry Andric unsigned DenseMapInfo<GEPValue>::getHashValue(const GEPValue &Val) {
6065f757f3fSDimitry Andric   auto *GEP = cast<GetElementPtrInst>(Val.Inst);
6075f757f3fSDimitry Andric   if (Val.ConstantOffset.has_value())
6085f757f3fSDimitry Andric     return hash_combine(GEP->getOpcode(), GEP->getPointerOperand(),
6095f757f3fSDimitry Andric                         Val.ConstantOffset.value());
6105f757f3fSDimitry Andric   return hash_combine(
6115f757f3fSDimitry Andric       GEP->getOpcode(),
6125f757f3fSDimitry Andric       hash_combine_range(GEP->value_op_begin(), GEP->value_op_end()));
6135f757f3fSDimitry Andric }
6145f757f3fSDimitry Andric 
6155f757f3fSDimitry Andric bool DenseMapInfo<GEPValue>::isEqual(const GEPValue &LHS, const GEPValue &RHS) {
6165f757f3fSDimitry Andric   if (LHS.isSentinel() || RHS.isSentinel())
6175f757f3fSDimitry Andric     return LHS.Inst == RHS.Inst;
6185f757f3fSDimitry Andric   auto *LGEP = cast<GetElementPtrInst>(LHS.Inst);
6195f757f3fSDimitry Andric   auto *RGEP = cast<GetElementPtrInst>(RHS.Inst);
6205f757f3fSDimitry Andric   if (LGEP->getPointerOperand() != RGEP->getPointerOperand())
6215f757f3fSDimitry Andric     return false;
6225f757f3fSDimitry Andric   if (LHS.ConstantOffset.has_value() && RHS.ConstantOffset.has_value())
6235f757f3fSDimitry Andric     return LHS.ConstantOffset.value() == RHS.ConstantOffset.value();
6245f757f3fSDimitry Andric   return LGEP->isIdenticalToWhenDefined(RGEP);
6255f757f3fSDimitry Andric }
6265f757f3fSDimitry Andric 
6275f757f3fSDimitry Andric //===----------------------------------------------------------------------===//
6280b57cec5SDimitry Andric // EarlyCSE implementation
6290b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
6300b57cec5SDimitry Andric 
6310b57cec5SDimitry Andric namespace {
6320b57cec5SDimitry Andric 
6330b57cec5SDimitry Andric /// A simple and fast domtree-based CSE pass.
6340b57cec5SDimitry Andric ///
6350b57cec5SDimitry Andric /// This pass does a simple depth-first walk over the dominator tree,
6360b57cec5SDimitry Andric /// eliminating trivially redundant instructions and using instsimplify to
6370b57cec5SDimitry Andric /// canonicalize things as it goes. It is intended to be fast and catch obvious
6380b57cec5SDimitry Andric /// cases so that instcombine and other passes are more effective. It is
6390b57cec5SDimitry Andric /// expected that a later pass of GVN will catch the interesting/hard cases.
6400b57cec5SDimitry Andric class EarlyCSE {
6410b57cec5SDimitry Andric public:
6420b57cec5SDimitry Andric   const TargetLibraryInfo &TLI;
6430b57cec5SDimitry Andric   const TargetTransformInfo &TTI;
6440b57cec5SDimitry Andric   DominatorTree &DT;
6450b57cec5SDimitry Andric   AssumptionCache &AC;
6460b57cec5SDimitry Andric   const SimplifyQuery SQ;
6470b57cec5SDimitry Andric   MemorySSA *MSSA;
6480b57cec5SDimitry Andric   std::unique_ptr<MemorySSAUpdater> MSSAUpdater;
6490b57cec5SDimitry Andric 
6500b57cec5SDimitry Andric   using AllocatorTy =
6510b57cec5SDimitry Andric       RecyclingAllocator<BumpPtrAllocator,
6520b57cec5SDimitry Andric                          ScopedHashTableVal<SimpleValue, Value *>>;
6530b57cec5SDimitry Andric   using ScopedHTType =
6540b57cec5SDimitry Andric       ScopedHashTable<SimpleValue, Value *, DenseMapInfo<SimpleValue>,
6550b57cec5SDimitry Andric                       AllocatorTy>;
6560b57cec5SDimitry Andric 
6570b57cec5SDimitry Andric   /// A scoped hash table of the current values of all of our simple
6580b57cec5SDimitry Andric   /// scalar expressions.
6590b57cec5SDimitry Andric   ///
6600b57cec5SDimitry Andric   /// As we walk down the domtree, we look to see if instructions are in this:
6610b57cec5SDimitry Andric   /// if so, we replace them with what we find, otherwise we insert them so
6620b57cec5SDimitry Andric   /// that dominated values can succeed in their lookup.
6630b57cec5SDimitry Andric   ScopedHTType AvailableValues;
6640b57cec5SDimitry Andric 
6650b57cec5SDimitry Andric   /// A scoped hash table of the current values of previously encountered
6660b57cec5SDimitry Andric   /// memory locations.
6670b57cec5SDimitry Andric   ///
6680b57cec5SDimitry Andric   /// This allows us to get efficient access to dominating loads or stores when
6690b57cec5SDimitry Andric   /// we have a fully redundant load.  In addition to the most recent load, we
6700b57cec5SDimitry Andric   /// keep track of a generation count of the read, which is compared against
6710b57cec5SDimitry Andric   /// the current generation count.  The current generation count is incremented
6720b57cec5SDimitry Andric   /// after every possibly writing memory operation, which ensures that we only
6730b57cec5SDimitry Andric   /// CSE loads with other loads that have no intervening store.  Ordering
6740b57cec5SDimitry Andric   /// events (such as fences or atomic instructions) increment the generation
6750b57cec5SDimitry Andric   /// count as well; essentially, we model these as writes to all possible
6760b57cec5SDimitry Andric   /// locations.  Note that atomic and/or volatile loads and stores can be
6770b57cec5SDimitry Andric   /// present the table; it is the responsibility of the consumer to inspect
6780b57cec5SDimitry Andric   /// the atomicity/volatility if needed.
6790b57cec5SDimitry Andric   struct LoadValue {
6800b57cec5SDimitry Andric     Instruction *DefInst = nullptr;
6810b57cec5SDimitry Andric     unsigned Generation = 0;
6820b57cec5SDimitry Andric     int MatchingId = -1;
6830b57cec5SDimitry Andric     bool IsAtomic = false;
68406c3fb27SDimitry Andric     bool IsLoad = false;
6850b57cec5SDimitry Andric 
6860b57cec5SDimitry Andric     LoadValue() = default;
6870b57cec5SDimitry Andric     LoadValue(Instruction *Inst, unsigned Generation, unsigned MatchingId,
68806c3fb27SDimitry Andric               bool IsAtomic, bool IsLoad)
6890b57cec5SDimitry Andric         : DefInst(Inst), Generation(Generation), MatchingId(MatchingId),
69006c3fb27SDimitry Andric           IsAtomic(IsAtomic), IsLoad(IsLoad) {}
6910b57cec5SDimitry Andric   };
6920b57cec5SDimitry Andric 
6930b57cec5SDimitry Andric   using LoadMapAllocator =
6940b57cec5SDimitry Andric       RecyclingAllocator<BumpPtrAllocator,
6950b57cec5SDimitry Andric                          ScopedHashTableVal<Value *, LoadValue>>;
6960b57cec5SDimitry Andric   using LoadHTType =
6970b57cec5SDimitry Andric       ScopedHashTable<Value *, LoadValue, DenseMapInfo<Value *>,
6980b57cec5SDimitry Andric                       LoadMapAllocator>;
6990b57cec5SDimitry Andric 
7000b57cec5SDimitry Andric   LoadHTType AvailableLoads;
7010b57cec5SDimitry Andric 
7020b57cec5SDimitry Andric   // A scoped hash table mapping memory locations (represented as typed
7030b57cec5SDimitry Andric   // addresses) to generation numbers at which that memory location became
7040b57cec5SDimitry Andric   // (henceforth indefinitely) invariant.
7050b57cec5SDimitry Andric   using InvariantMapAllocator =
7060b57cec5SDimitry Andric       RecyclingAllocator<BumpPtrAllocator,
7070b57cec5SDimitry Andric                          ScopedHashTableVal<MemoryLocation, unsigned>>;
7080b57cec5SDimitry Andric   using InvariantHTType =
7090b57cec5SDimitry Andric       ScopedHashTable<MemoryLocation, unsigned, DenseMapInfo<MemoryLocation>,
7100b57cec5SDimitry Andric                       InvariantMapAllocator>;
7110b57cec5SDimitry Andric   InvariantHTType AvailableInvariants;
7120b57cec5SDimitry Andric 
7130b57cec5SDimitry Andric   /// A scoped hash table of the current values of read-only call
7140b57cec5SDimitry Andric   /// values.
7150b57cec5SDimitry Andric   ///
7160b57cec5SDimitry Andric   /// It uses the same generation count as loads.
7170b57cec5SDimitry Andric   using CallHTType =
7180b57cec5SDimitry Andric       ScopedHashTable<CallValue, std::pair<Instruction *, unsigned>>;
7190b57cec5SDimitry Andric   CallHTType AvailableCalls;
7200b57cec5SDimitry Andric 
7215f757f3fSDimitry Andric   using GEPMapAllocatorTy =
7225f757f3fSDimitry Andric       RecyclingAllocator<BumpPtrAllocator,
7235f757f3fSDimitry Andric                          ScopedHashTableVal<GEPValue, Value *>>;
7245f757f3fSDimitry Andric   using GEPHTType = ScopedHashTable<GEPValue, Value *, DenseMapInfo<GEPValue>,
7255f757f3fSDimitry Andric                                     GEPMapAllocatorTy>;
7265f757f3fSDimitry Andric   GEPHTType AvailableGEPs;
7275f757f3fSDimitry Andric 
7280b57cec5SDimitry Andric   /// This is the current generation of the memory value.
7290b57cec5SDimitry Andric   unsigned CurrentGeneration = 0;
7300b57cec5SDimitry Andric 
7310b57cec5SDimitry Andric   /// Set up the EarlyCSE runner for a particular function.
7320b57cec5SDimitry Andric   EarlyCSE(const DataLayout &DL, const TargetLibraryInfo &TLI,
7330b57cec5SDimitry Andric            const TargetTransformInfo &TTI, DominatorTree &DT,
7340b57cec5SDimitry Andric            AssumptionCache &AC, MemorySSA *MSSA)
7350b57cec5SDimitry Andric       : TLI(TLI), TTI(TTI), DT(DT), AC(AC), SQ(DL, &TLI, &DT, &AC), MSSA(MSSA),
7368bcb0991SDimitry Andric         MSSAUpdater(std::make_unique<MemorySSAUpdater>(MSSA)) {}
7370b57cec5SDimitry Andric 
7380b57cec5SDimitry Andric   bool run();
7390b57cec5SDimitry Andric 
7400b57cec5SDimitry Andric private:
7410b57cec5SDimitry Andric   unsigned ClobberCounter = 0;
7420b57cec5SDimitry Andric   // Almost a POD, but needs to call the constructors for the scoped hash
7430b57cec5SDimitry Andric   // tables so that a new scope gets pushed on. These are RAII so that the
7440b57cec5SDimitry Andric   // scope gets popped when the NodeScope is destroyed.
7450b57cec5SDimitry Andric   class NodeScope {
7460b57cec5SDimitry Andric   public:
7470b57cec5SDimitry Andric     NodeScope(ScopedHTType &AvailableValues, LoadHTType &AvailableLoads,
7485f757f3fSDimitry Andric               InvariantHTType &AvailableInvariants, CallHTType &AvailableCalls,
7495f757f3fSDimitry Andric               GEPHTType &AvailableGEPs)
7500b57cec5SDimitry Andric         : Scope(AvailableValues), LoadScope(AvailableLoads),
7515f757f3fSDimitry Andric           InvariantScope(AvailableInvariants), CallScope(AvailableCalls),
7525f757f3fSDimitry Andric           GEPScope(AvailableGEPs) {}
7530b57cec5SDimitry Andric     NodeScope(const NodeScope &) = delete;
7540b57cec5SDimitry Andric     NodeScope &operator=(const NodeScope &) = delete;
7550b57cec5SDimitry Andric 
7560b57cec5SDimitry Andric   private:
7570b57cec5SDimitry Andric     ScopedHTType::ScopeTy Scope;
7580b57cec5SDimitry Andric     LoadHTType::ScopeTy LoadScope;
7590b57cec5SDimitry Andric     InvariantHTType::ScopeTy InvariantScope;
7600b57cec5SDimitry Andric     CallHTType::ScopeTy CallScope;
7615f757f3fSDimitry Andric     GEPHTType::ScopeTy GEPScope;
7620b57cec5SDimitry Andric   };
7630b57cec5SDimitry Andric 
7640b57cec5SDimitry Andric   // Contains all the needed information to create a stack for doing a depth
7650b57cec5SDimitry Andric   // first traversal of the tree. This includes scopes for values, loads, and
7660b57cec5SDimitry Andric   // calls as well as the generation. There is a child iterator so that the
7670b57cec5SDimitry Andric   // children do not need to be store separately.
7680b57cec5SDimitry Andric   class StackNode {
7690b57cec5SDimitry Andric   public:
7700b57cec5SDimitry Andric     StackNode(ScopedHTType &AvailableValues, LoadHTType &AvailableLoads,
7710b57cec5SDimitry Andric               InvariantHTType &AvailableInvariants, CallHTType &AvailableCalls,
7725f757f3fSDimitry Andric               GEPHTType &AvailableGEPs, unsigned cg, DomTreeNode *n,
7735f757f3fSDimitry Andric               DomTreeNode::const_iterator child,
7745ffd83dbSDimitry Andric               DomTreeNode::const_iterator end)
7750b57cec5SDimitry Andric         : CurrentGeneration(cg), ChildGeneration(cg), Node(n), ChildIter(child),
7760b57cec5SDimitry Andric           EndIter(end),
7770b57cec5SDimitry Andric           Scopes(AvailableValues, AvailableLoads, AvailableInvariants,
7785f757f3fSDimitry Andric                  AvailableCalls, AvailableGEPs) {}
7790b57cec5SDimitry Andric     StackNode(const StackNode &) = delete;
7800b57cec5SDimitry Andric     StackNode &operator=(const StackNode &) = delete;
7810b57cec5SDimitry Andric 
7820b57cec5SDimitry Andric     // Accessors.
783e8d8bef9SDimitry Andric     unsigned currentGeneration() const { return CurrentGeneration; }
784e8d8bef9SDimitry Andric     unsigned childGeneration() const { return ChildGeneration; }
7850b57cec5SDimitry Andric     void childGeneration(unsigned generation) { ChildGeneration = generation; }
7860b57cec5SDimitry Andric     DomTreeNode *node() { return Node; }
787e8d8bef9SDimitry Andric     DomTreeNode::const_iterator childIter() const { return ChildIter; }
7880b57cec5SDimitry Andric 
7890b57cec5SDimitry Andric     DomTreeNode *nextChild() {
7900b57cec5SDimitry Andric       DomTreeNode *child = *ChildIter;
7910b57cec5SDimitry Andric       ++ChildIter;
7920b57cec5SDimitry Andric       return child;
7930b57cec5SDimitry Andric     }
7940b57cec5SDimitry Andric 
795e8d8bef9SDimitry Andric     DomTreeNode::const_iterator end() const { return EndIter; }
796e8d8bef9SDimitry Andric     bool isProcessed() const { return Processed; }
7970b57cec5SDimitry Andric     void process() { Processed = true; }
7980b57cec5SDimitry Andric 
7990b57cec5SDimitry Andric   private:
8000b57cec5SDimitry Andric     unsigned CurrentGeneration;
8010b57cec5SDimitry Andric     unsigned ChildGeneration;
8020b57cec5SDimitry Andric     DomTreeNode *Node;
8035ffd83dbSDimitry Andric     DomTreeNode::const_iterator ChildIter;
8045ffd83dbSDimitry Andric     DomTreeNode::const_iterator EndIter;
8050b57cec5SDimitry Andric     NodeScope Scopes;
8060b57cec5SDimitry Andric     bool Processed = false;
8070b57cec5SDimitry Andric   };
8080b57cec5SDimitry Andric 
8090b57cec5SDimitry Andric   /// Wrapper class to handle memory instructions, including loads,
8100b57cec5SDimitry Andric   /// stores and intrinsic loads and stores defined by the target.
8110b57cec5SDimitry Andric   class ParseMemoryInst {
8120b57cec5SDimitry Andric   public:
8130b57cec5SDimitry Andric     ParseMemoryInst(Instruction *Inst, const TargetTransformInfo &TTI)
8140b57cec5SDimitry Andric       : Inst(Inst) {
815e8d8bef9SDimitry Andric       if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Inst)) {
816e8d8bef9SDimitry Andric         IntrID = II->getIntrinsicID();
8170b57cec5SDimitry Andric         if (TTI.getTgtMemIntrinsic(II, Info))
818e8d8bef9SDimitry Andric           return;
819e8d8bef9SDimitry Andric         if (isHandledNonTargetIntrinsic(IntrID)) {
820e8d8bef9SDimitry Andric           switch (IntrID) {
821e8d8bef9SDimitry Andric           case Intrinsic::masked_load:
822e8d8bef9SDimitry Andric             Info.PtrVal = Inst->getOperand(0);
823e8d8bef9SDimitry Andric             Info.MatchingId = Intrinsic::masked_load;
824e8d8bef9SDimitry Andric             Info.ReadMem = true;
825e8d8bef9SDimitry Andric             Info.WriteMem = false;
826e8d8bef9SDimitry Andric             Info.IsVolatile = false;
827e8d8bef9SDimitry Andric             break;
828e8d8bef9SDimitry Andric           case Intrinsic::masked_store:
829e8d8bef9SDimitry Andric             Info.PtrVal = Inst->getOperand(1);
830e8d8bef9SDimitry Andric             // Use the ID of masked load as the "matching id". This will
831e8d8bef9SDimitry Andric             // prevent matching non-masked loads/stores with masked ones
832e8d8bef9SDimitry Andric             // (which could be done), but at the moment, the code here
833e8d8bef9SDimitry Andric             // does not support matching intrinsics with non-intrinsics,
834e8d8bef9SDimitry Andric             // so keep the MatchingIds specific to masked instructions
835e8d8bef9SDimitry Andric             // for now (TODO).
836e8d8bef9SDimitry Andric             Info.MatchingId = Intrinsic::masked_load;
837e8d8bef9SDimitry Andric             Info.ReadMem = false;
838e8d8bef9SDimitry Andric             Info.WriteMem = true;
839e8d8bef9SDimitry Andric             Info.IsVolatile = false;
840e8d8bef9SDimitry Andric             break;
841e8d8bef9SDimitry Andric           }
842e8d8bef9SDimitry Andric         }
843e8d8bef9SDimitry Andric       }
8440b57cec5SDimitry Andric     }
8450b57cec5SDimitry Andric 
846e8d8bef9SDimitry Andric     Instruction *get() { return Inst; }
847e8d8bef9SDimitry Andric     const Instruction *get() const { return Inst; }
848e8d8bef9SDimitry Andric 
8490b57cec5SDimitry Andric     bool isLoad() const {
850e8d8bef9SDimitry Andric       if (IntrID != 0)
851e8d8bef9SDimitry Andric         return Info.ReadMem;
8520b57cec5SDimitry Andric       return isa<LoadInst>(Inst);
8530b57cec5SDimitry Andric     }
8540b57cec5SDimitry Andric 
8550b57cec5SDimitry Andric     bool isStore() const {
856e8d8bef9SDimitry Andric       if (IntrID != 0)
857e8d8bef9SDimitry Andric         return Info.WriteMem;
8580b57cec5SDimitry Andric       return isa<StoreInst>(Inst);
8590b57cec5SDimitry Andric     }
8600b57cec5SDimitry Andric 
8610b57cec5SDimitry Andric     bool isAtomic() const {
862e8d8bef9SDimitry Andric       if (IntrID != 0)
8630b57cec5SDimitry Andric         return Info.Ordering != AtomicOrdering::NotAtomic;
8640b57cec5SDimitry Andric       return Inst->isAtomic();
8650b57cec5SDimitry Andric     }
8660b57cec5SDimitry Andric 
8670b57cec5SDimitry Andric     bool isUnordered() const {
868e8d8bef9SDimitry Andric       if (IntrID != 0)
8690b57cec5SDimitry Andric         return Info.isUnordered();
8700b57cec5SDimitry Andric 
8710b57cec5SDimitry Andric       if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) {
8720b57cec5SDimitry Andric         return LI->isUnordered();
8730b57cec5SDimitry Andric       } else if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
8740b57cec5SDimitry Andric         return SI->isUnordered();
8750b57cec5SDimitry Andric       }
8760b57cec5SDimitry Andric       // Conservative answer
8770b57cec5SDimitry Andric       return !Inst->isAtomic();
8780b57cec5SDimitry Andric     }
8790b57cec5SDimitry Andric 
8800b57cec5SDimitry Andric     bool isVolatile() const {
881e8d8bef9SDimitry Andric       if (IntrID != 0)
8820b57cec5SDimitry Andric         return Info.IsVolatile;
8830b57cec5SDimitry Andric 
8840b57cec5SDimitry Andric       if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) {
8850b57cec5SDimitry Andric         return LI->isVolatile();
8860b57cec5SDimitry Andric       } else if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
8870b57cec5SDimitry Andric         return SI->isVolatile();
8880b57cec5SDimitry Andric       }
8890b57cec5SDimitry Andric       // Conservative answer
8900b57cec5SDimitry Andric       return true;
8910b57cec5SDimitry Andric     }
8920b57cec5SDimitry Andric 
8930b57cec5SDimitry Andric     bool isInvariantLoad() const {
8940b57cec5SDimitry Andric       if (auto *LI = dyn_cast<LoadInst>(Inst))
8958bcb0991SDimitry Andric         return LI->hasMetadata(LLVMContext::MD_invariant_load);
8960b57cec5SDimitry Andric       return false;
8970b57cec5SDimitry Andric     }
8980b57cec5SDimitry Andric 
8990b57cec5SDimitry Andric     bool isValid() const { return getPointerOperand() != nullptr; }
9000b57cec5SDimitry Andric 
9010b57cec5SDimitry Andric     // For regular (non-intrinsic) loads/stores, this is set to -1. For
9020b57cec5SDimitry Andric     // intrinsic loads/stores, the id is retrieved from the corresponding
9030b57cec5SDimitry Andric     // field in the MemIntrinsicInfo structure.  That field contains
9040b57cec5SDimitry Andric     // non-negative values only.
9050b57cec5SDimitry Andric     int getMatchingId() const {
906e8d8bef9SDimitry Andric       if (IntrID != 0)
907e8d8bef9SDimitry Andric         return Info.MatchingId;
9080b57cec5SDimitry Andric       return -1;
9090b57cec5SDimitry Andric     }
9100b57cec5SDimitry Andric 
9110b57cec5SDimitry Andric     Value *getPointerOperand() const {
912e8d8bef9SDimitry Andric       if (IntrID != 0)
913e8d8bef9SDimitry Andric         return Info.PtrVal;
9140b57cec5SDimitry Andric       return getLoadStorePointerOperand(Inst);
9150b57cec5SDimitry Andric     }
9160b57cec5SDimitry Andric 
91781ad6265SDimitry Andric     Type *getValueType() const {
91881ad6265SDimitry Andric       // TODO: handle target-specific intrinsics.
91906c3fb27SDimitry Andric       return Inst->getAccessType();
92081ad6265SDimitry Andric     }
92181ad6265SDimitry Andric 
9220b57cec5SDimitry Andric     bool mayReadFromMemory() const {
923e8d8bef9SDimitry Andric       if (IntrID != 0)
924e8d8bef9SDimitry Andric         return Info.ReadMem;
9250b57cec5SDimitry Andric       return Inst->mayReadFromMemory();
9260b57cec5SDimitry Andric     }
9270b57cec5SDimitry Andric 
9280b57cec5SDimitry Andric     bool mayWriteToMemory() const {
929e8d8bef9SDimitry Andric       if (IntrID != 0)
930e8d8bef9SDimitry Andric         return Info.WriteMem;
9310b57cec5SDimitry Andric       return Inst->mayWriteToMemory();
9320b57cec5SDimitry Andric     }
9330b57cec5SDimitry Andric 
9340b57cec5SDimitry Andric   private:
935e8d8bef9SDimitry Andric     Intrinsic::ID IntrID = 0;
9360b57cec5SDimitry Andric     MemIntrinsicInfo Info;
9370b57cec5SDimitry Andric     Instruction *Inst;
9380b57cec5SDimitry Andric   };
9390b57cec5SDimitry Andric 
940e8d8bef9SDimitry Andric   // This function is to prevent accidentally passing a non-target
941e8d8bef9SDimitry Andric   // intrinsic ID to TargetTransformInfo.
942e8d8bef9SDimitry Andric   static bool isHandledNonTargetIntrinsic(Intrinsic::ID ID) {
943e8d8bef9SDimitry Andric     switch (ID) {
944e8d8bef9SDimitry Andric     case Intrinsic::masked_load:
945e8d8bef9SDimitry Andric     case Intrinsic::masked_store:
946e8d8bef9SDimitry Andric       return true;
947e8d8bef9SDimitry Andric     }
948e8d8bef9SDimitry Andric     return false;
949e8d8bef9SDimitry Andric   }
950e8d8bef9SDimitry Andric   static bool isHandledNonTargetIntrinsic(const Value *V) {
951e8d8bef9SDimitry Andric     if (auto *II = dyn_cast<IntrinsicInst>(V))
952e8d8bef9SDimitry Andric       return isHandledNonTargetIntrinsic(II->getIntrinsicID());
953e8d8bef9SDimitry Andric     return false;
954e8d8bef9SDimitry Andric   }
955e8d8bef9SDimitry Andric 
9560b57cec5SDimitry Andric   bool processNode(DomTreeNode *Node);
9570b57cec5SDimitry Andric 
9580b57cec5SDimitry Andric   bool handleBranchCondition(Instruction *CondInst, const BranchInst *BI,
9590b57cec5SDimitry Andric                              const BasicBlock *BB, const BasicBlock *Pred);
9600b57cec5SDimitry Andric 
961e8d8bef9SDimitry Andric   Value *getMatchingValue(LoadValue &InVal, ParseMemoryInst &MemInst,
962e8d8bef9SDimitry Andric                           unsigned CurrentGeneration);
963e8d8bef9SDimitry Andric 
964e8d8bef9SDimitry Andric   bool overridingStores(const ParseMemoryInst &Earlier,
965e8d8bef9SDimitry Andric                         const ParseMemoryInst &Later);
966e8d8bef9SDimitry Andric 
9670b57cec5SDimitry Andric   Value *getOrCreateResult(Value *Inst, Type *ExpectedType) const {
96804eeddc0SDimitry Andric     // TODO: We could insert relevant casts on type mismatch here.
9690b57cec5SDimitry Andric     if (auto *LI = dyn_cast<LoadInst>(Inst))
97004eeddc0SDimitry Andric       return LI->getType() == ExpectedType ? LI : nullptr;
971bdd1243dSDimitry Andric     if (auto *SI = dyn_cast<StoreInst>(Inst)) {
97204eeddc0SDimitry Andric       Value *V = SI->getValueOperand();
97304eeddc0SDimitry Andric       return V->getType() == ExpectedType ? V : nullptr;
97404eeddc0SDimitry Andric     }
9750b57cec5SDimitry Andric     assert(isa<IntrinsicInst>(Inst) && "Instruction not supported");
976e8d8bef9SDimitry Andric     auto *II = cast<IntrinsicInst>(Inst);
977e8d8bef9SDimitry Andric     if (isHandledNonTargetIntrinsic(II->getIntrinsicID()))
978e8d8bef9SDimitry Andric       return getOrCreateResultNonTargetMemIntrinsic(II, ExpectedType);
979e8d8bef9SDimitry Andric     return TTI.getOrCreateResultFromMemIntrinsic(II, ExpectedType);
980e8d8bef9SDimitry Andric   }
981e8d8bef9SDimitry Andric 
982e8d8bef9SDimitry Andric   Value *getOrCreateResultNonTargetMemIntrinsic(IntrinsicInst *II,
983e8d8bef9SDimitry Andric                                                 Type *ExpectedType) const {
984bdd1243dSDimitry Andric     // TODO: We could insert relevant casts on type mismatch here.
985e8d8bef9SDimitry Andric     switch (II->getIntrinsicID()) {
986e8d8bef9SDimitry Andric     case Intrinsic::masked_load:
987bdd1243dSDimitry Andric       return II->getType() == ExpectedType ? II : nullptr;
988bdd1243dSDimitry Andric     case Intrinsic::masked_store: {
989bdd1243dSDimitry Andric       Value *V = II->getOperand(0);
990bdd1243dSDimitry Andric       return V->getType() == ExpectedType ? V : nullptr;
991bdd1243dSDimitry Andric     }
992e8d8bef9SDimitry Andric     }
993e8d8bef9SDimitry Andric     return nullptr;
9940b57cec5SDimitry Andric   }
9950b57cec5SDimitry Andric 
9960b57cec5SDimitry Andric   /// Return true if the instruction is known to only operate on memory
9970b57cec5SDimitry Andric   /// provably invariant in the given "generation".
9980b57cec5SDimitry Andric   bool isOperatingOnInvariantMemAt(Instruction *I, unsigned GenAt);
9990b57cec5SDimitry Andric 
10000b57cec5SDimitry Andric   bool isSameMemGeneration(unsigned EarlierGeneration, unsigned LaterGeneration,
10010b57cec5SDimitry Andric                            Instruction *EarlierInst, Instruction *LaterInst);
10020b57cec5SDimitry Andric 
1003e8d8bef9SDimitry Andric   bool isNonTargetIntrinsicMatch(const IntrinsicInst *Earlier,
1004e8d8bef9SDimitry Andric                                  const IntrinsicInst *Later) {
1005e8d8bef9SDimitry Andric     auto IsSubmask = [](const Value *Mask0, const Value *Mask1) {
1006e8d8bef9SDimitry Andric       // Is Mask0 a submask of Mask1?
1007e8d8bef9SDimitry Andric       if (Mask0 == Mask1)
1008e8d8bef9SDimitry Andric         return true;
1009e8d8bef9SDimitry Andric       if (isa<UndefValue>(Mask0) || isa<UndefValue>(Mask1))
1010e8d8bef9SDimitry Andric         return false;
1011e8d8bef9SDimitry Andric       auto *Vec0 = dyn_cast<ConstantVector>(Mask0);
1012e8d8bef9SDimitry Andric       auto *Vec1 = dyn_cast<ConstantVector>(Mask1);
1013e8d8bef9SDimitry Andric       if (!Vec0 || !Vec1)
1014e8d8bef9SDimitry Andric         return false;
1015bdd1243dSDimitry Andric       if (Vec0->getType() != Vec1->getType())
1016bdd1243dSDimitry Andric         return false;
1017e8d8bef9SDimitry Andric       for (int i = 0, e = Vec0->getNumOperands(); i != e; ++i) {
1018e8d8bef9SDimitry Andric         Constant *Elem0 = Vec0->getOperand(i);
1019e8d8bef9SDimitry Andric         Constant *Elem1 = Vec1->getOperand(i);
1020e8d8bef9SDimitry Andric         auto *Int0 = dyn_cast<ConstantInt>(Elem0);
1021e8d8bef9SDimitry Andric         if (Int0 && Int0->isZero())
1022e8d8bef9SDimitry Andric           continue;
1023e8d8bef9SDimitry Andric         auto *Int1 = dyn_cast<ConstantInt>(Elem1);
1024e8d8bef9SDimitry Andric         if (Int1 && !Int1->isZero())
1025e8d8bef9SDimitry Andric           continue;
1026e8d8bef9SDimitry Andric         if (isa<UndefValue>(Elem0) || isa<UndefValue>(Elem1))
1027e8d8bef9SDimitry Andric           return false;
1028e8d8bef9SDimitry Andric         if (Elem0 == Elem1)
1029e8d8bef9SDimitry Andric           continue;
1030e8d8bef9SDimitry Andric         return false;
1031e8d8bef9SDimitry Andric       }
1032e8d8bef9SDimitry Andric       return true;
1033e8d8bef9SDimitry Andric     };
1034e8d8bef9SDimitry Andric     auto PtrOp = [](const IntrinsicInst *II) {
1035e8d8bef9SDimitry Andric       if (II->getIntrinsicID() == Intrinsic::masked_load)
1036e8d8bef9SDimitry Andric         return II->getOperand(0);
1037e8d8bef9SDimitry Andric       if (II->getIntrinsicID() == Intrinsic::masked_store)
1038e8d8bef9SDimitry Andric         return II->getOperand(1);
1039e8d8bef9SDimitry Andric       llvm_unreachable("Unexpected IntrinsicInst");
1040e8d8bef9SDimitry Andric     };
1041e8d8bef9SDimitry Andric     auto MaskOp = [](const IntrinsicInst *II) {
1042e8d8bef9SDimitry Andric       if (II->getIntrinsicID() == Intrinsic::masked_load)
1043e8d8bef9SDimitry Andric         return II->getOperand(2);
1044e8d8bef9SDimitry Andric       if (II->getIntrinsicID() == Intrinsic::masked_store)
1045e8d8bef9SDimitry Andric         return II->getOperand(3);
1046e8d8bef9SDimitry Andric       llvm_unreachable("Unexpected IntrinsicInst");
1047e8d8bef9SDimitry Andric     };
1048e8d8bef9SDimitry Andric     auto ThruOp = [](const IntrinsicInst *II) {
1049e8d8bef9SDimitry Andric       if (II->getIntrinsicID() == Intrinsic::masked_load)
1050e8d8bef9SDimitry Andric         return II->getOperand(3);
1051e8d8bef9SDimitry Andric       llvm_unreachable("Unexpected IntrinsicInst");
1052e8d8bef9SDimitry Andric     };
1053e8d8bef9SDimitry Andric 
1054e8d8bef9SDimitry Andric     if (PtrOp(Earlier) != PtrOp(Later))
1055e8d8bef9SDimitry Andric       return false;
1056e8d8bef9SDimitry Andric 
1057e8d8bef9SDimitry Andric     Intrinsic::ID IDE = Earlier->getIntrinsicID();
1058e8d8bef9SDimitry Andric     Intrinsic::ID IDL = Later->getIntrinsicID();
1059e8d8bef9SDimitry Andric     // We could really use specific intrinsic classes for masked loads
1060e8d8bef9SDimitry Andric     // and stores in IntrinsicInst.h.
1061e8d8bef9SDimitry Andric     if (IDE == Intrinsic::masked_load && IDL == Intrinsic::masked_load) {
1062e8d8bef9SDimitry Andric       // Trying to replace later masked load with the earlier one.
1063e8d8bef9SDimitry Andric       // Check that the pointers are the same, and
1064e8d8bef9SDimitry Andric       // - masks and pass-throughs are the same, or
1065e8d8bef9SDimitry Andric       // - replacee's pass-through is "undef" and replacer's mask is a
1066e8d8bef9SDimitry Andric       //   super-set of the replacee's mask.
1067e8d8bef9SDimitry Andric       if (MaskOp(Earlier) == MaskOp(Later) && ThruOp(Earlier) == ThruOp(Later))
1068e8d8bef9SDimitry Andric         return true;
1069e8d8bef9SDimitry Andric       if (!isa<UndefValue>(ThruOp(Later)))
1070e8d8bef9SDimitry Andric         return false;
1071e8d8bef9SDimitry Andric       return IsSubmask(MaskOp(Later), MaskOp(Earlier));
1072e8d8bef9SDimitry Andric     }
1073e8d8bef9SDimitry Andric     if (IDE == Intrinsic::masked_store && IDL == Intrinsic::masked_load) {
1074e8d8bef9SDimitry Andric       // Trying to replace a load of a stored value with the store's value.
1075e8d8bef9SDimitry Andric       // Check that the pointers are the same, and
1076e8d8bef9SDimitry Andric       // - load's mask is a subset of store's mask, and
1077e8d8bef9SDimitry Andric       // - load's pass-through is "undef".
1078e8d8bef9SDimitry Andric       if (!IsSubmask(MaskOp(Later), MaskOp(Earlier)))
1079e8d8bef9SDimitry Andric         return false;
1080e8d8bef9SDimitry Andric       return isa<UndefValue>(ThruOp(Later));
1081e8d8bef9SDimitry Andric     }
1082e8d8bef9SDimitry Andric     if (IDE == Intrinsic::masked_load && IDL == Intrinsic::masked_store) {
1083e8d8bef9SDimitry Andric       // Trying to remove a store of the loaded value.
1084e8d8bef9SDimitry Andric       // Check that the pointers are the same, and
1085e8d8bef9SDimitry Andric       // - store's mask is a subset of the load's mask.
1086e8d8bef9SDimitry Andric       return IsSubmask(MaskOp(Later), MaskOp(Earlier));
1087e8d8bef9SDimitry Andric     }
1088e8d8bef9SDimitry Andric     if (IDE == Intrinsic::masked_store && IDL == Intrinsic::masked_store) {
1089e8d8bef9SDimitry Andric       // Trying to remove a dead store (earlier).
1090e8d8bef9SDimitry Andric       // Check that the pointers are the same,
1091e8d8bef9SDimitry Andric       // - the to-be-removed store's mask is a subset of the other store's
1092e8d8bef9SDimitry Andric       //   mask.
1093e8d8bef9SDimitry Andric       return IsSubmask(MaskOp(Earlier), MaskOp(Later));
1094e8d8bef9SDimitry Andric     }
1095e8d8bef9SDimitry Andric     return false;
1096e8d8bef9SDimitry Andric   }
1097e8d8bef9SDimitry Andric 
10985ffd83dbSDimitry Andric   void removeMSSA(Instruction &Inst) {
10990b57cec5SDimitry Andric     if (!MSSA)
11000b57cec5SDimitry Andric       return;
11010b57cec5SDimitry Andric     if (VerifyMemorySSA)
11020b57cec5SDimitry Andric       MSSA->verifyMemorySSA();
11030b57cec5SDimitry Andric     // Removing a store here can leave MemorySSA in an unoptimized state by
11040b57cec5SDimitry Andric     // creating MemoryPhis that have identical arguments and by creating
11050b57cec5SDimitry Andric     // MemoryUses whose defining access is not an actual clobber. The phi case
11060b57cec5SDimitry Andric     // is handled by MemorySSA when passing OptimizePhis = true to
11070b57cec5SDimitry Andric     // removeMemoryAccess.  The non-optimized MemoryUse case is lazily updated
11080b57cec5SDimitry Andric     // by MemorySSA's getClobberingMemoryAccess.
11095ffd83dbSDimitry Andric     MSSAUpdater->removeMemoryAccess(&Inst, true);
11100b57cec5SDimitry Andric   }
11110b57cec5SDimitry Andric };
11120b57cec5SDimitry Andric 
11130b57cec5SDimitry Andric } // end anonymous namespace
11140b57cec5SDimitry Andric 
11150b57cec5SDimitry Andric /// Determine if the memory referenced by LaterInst is from the same heap
11160b57cec5SDimitry Andric /// version as EarlierInst.
11170b57cec5SDimitry Andric /// This is currently called in two scenarios:
11180b57cec5SDimitry Andric ///
11190b57cec5SDimitry Andric ///   load p
11200b57cec5SDimitry Andric ///   ...
11210b57cec5SDimitry Andric ///   load p
11220b57cec5SDimitry Andric ///
11230b57cec5SDimitry Andric /// and
11240b57cec5SDimitry Andric ///
11250b57cec5SDimitry Andric ///   x = load p
11260b57cec5SDimitry Andric ///   ...
11270b57cec5SDimitry Andric ///   store x, p
11280b57cec5SDimitry Andric ///
11290b57cec5SDimitry Andric /// in both cases we want to verify that there are no possible writes to the
11300b57cec5SDimitry Andric /// memory referenced by p between the earlier and later instruction.
11310b57cec5SDimitry Andric bool EarlyCSE::isSameMemGeneration(unsigned EarlierGeneration,
11320b57cec5SDimitry Andric                                    unsigned LaterGeneration,
11330b57cec5SDimitry Andric                                    Instruction *EarlierInst,
11340b57cec5SDimitry Andric                                    Instruction *LaterInst) {
11350b57cec5SDimitry Andric   // Check the simple memory generation tracking first.
11360b57cec5SDimitry Andric   if (EarlierGeneration == LaterGeneration)
11370b57cec5SDimitry Andric     return true;
11380b57cec5SDimitry Andric 
11390b57cec5SDimitry Andric   if (!MSSA)
11400b57cec5SDimitry Andric     return false;
11410b57cec5SDimitry Andric 
11420b57cec5SDimitry Andric   // If MemorySSA has determined that one of EarlierInst or LaterInst does not
11430b57cec5SDimitry Andric   // read/write memory, then we can safely return true here.
11440b57cec5SDimitry Andric   // FIXME: We could be more aggressive when checking doesNotAccessMemory(),
11450b57cec5SDimitry Andric   // onlyReadsMemory(), mayReadFromMemory(), and mayWriteToMemory() in this pass
11460b57cec5SDimitry Andric   // by also checking the MemorySSA MemoryAccess on the instruction.  Initial
11470b57cec5SDimitry Andric   // experiments suggest this isn't worthwhile, at least for C/C++ code compiled
11480b57cec5SDimitry Andric   // with the default optimization pipeline.
11490b57cec5SDimitry Andric   auto *EarlierMA = MSSA->getMemoryAccess(EarlierInst);
11500b57cec5SDimitry Andric   if (!EarlierMA)
11510b57cec5SDimitry Andric     return true;
11520b57cec5SDimitry Andric   auto *LaterMA = MSSA->getMemoryAccess(LaterInst);
11530b57cec5SDimitry Andric   if (!LaterMA)
11540b57cec5SDimitry Andric     return true;
11550b57cec5SDimitry Andric 
11560b57cec5SDimitry Andric   // Since we know LaterDef dominates LaterInst and EarlierInst dominates
11570b57cec5SDimitry Andric   // LaterInst, if LaterDef dominates EarlierInst then it can't occur between
11580b57cec5SDimitry Andric   // EarlierInst and LaterInst and neither can any other write that potentially
11590b57cec5SDimitry Andric   // clobbers LaterInst.
11600b57cec5SDimitry Andric   MemoryAccess *LaterDef;
11610b57cec5SDimitry Andric   if (ClobberCounter < EarlyCSEMssaOptCap) {
11620b57cec5SDimitry Andric     LaterDef = MSSA->getWalker()->getClobberingMemoryAccess(LaterInst);
11630b57cec5SDimitry Andric     ClobberCounter++;
11640b57cec5SDimitry Andric   } else
11650b57cec5SDimitry Andric     LaterDef = LaterMA->getDefiningAccess();
11660b57cec5SDimitry Andric 
11670b57cec5SDimitry Andric   return MSSA->dominates(LaterDef, EarlierMA);
11680b57cec5SDimitry Andric }
11690b57cec5SDimitry Andric 
11700b57cec5SDimitry Andric bool EarlyCSE::isOperatingOnInvariantMemAt(Instruction *I, unsigned GenAt) {
11710b57cec5SDimitry Andric   // A location loaded from with an invariant_load is assumed to *never* change
11720b57cec5SDimitry Andric   // within the visible scope of the compilation.
11730b57cec5SDimitry Andric   if (auto *LI = dyn_cast<LoadInst>(I))
11748bcb0991SDimitry Andric     if (LI->hasMetadata(LLVMContext::MD_invariant_load))
11750b57cec5SDimitry Andric       return true;
11760b57cec5SDimitry Andric 
11770b57cec5SDimitry Andric   auto MemLocOpt = MemoryLocation::getOrNone(I);
11780b57cec5SDimitry Andric   if (!MemLocOpt)
11790b57cec5SDimitry Andric     // "target" intrinsic forms of loads aren't currently known to
11800b57cec5SDimitry Andric     // MemoryLocation::get.  TODO
11810b57cec5SDimitry Andric     return false;
11820b57cec5SDimitry Andric   MemoryLocation MemLoc = *MemLocOpt;
11830b57cec5SDimitry Andric   if (!AvailableInvariants.count(MemLoc))
11840b57cec5SDimitry Andric     return false;
11850b57cec5SDimitry Andric 
11860b57cec5SDimitry Andric   // Is the generation at which this became invariant older than the
11870b57cec5SDimitry Andric   // current one?
11880b57cec5SDimitry Andric   return AvailableInvariants.lookup(MemLoc) <= GenAt;
11890b57cec5SDimitry Andric }
11900b57cec5SDimitry Andric 
11910b57cec5SDimitry Andric bool EarlyCSE::handleBranchCondition(Instruction *CondInst,
11920b57cec5SDimitry Andric                                      const BranchInst *BI, const BasicBlock *BB,
11930b57cec5SDimitry Andric                                      const BasicBlock *Pred) {
11940b57cec5SDimitry Andric   assert(BI->isConditional() && "Should be a conditional branch!");
11950b57cec5SDimitry Andric   assert(BI->getCondition() == CondInst && "Wrong condition?");
11960b57cec5SDimitry Andric   assert(BI->getSuccessor(0) == BB || BI->getSuccessor(1) == BB);
11970b57cec5SDimitry Andric   auto *TorF = (BI->getSuccessor(0) == BB)
11980b57cec5SDimitry Andric                    ? ConstantInt::getTrue(BB->getContext())
11990b57cec5SDimitry Andric                    : ConstantInt::getFalse(BB->getContext());
1200e8d8bef9SDimitry Andric   auto MatchBinOp = [](Instruction *I, unsigned Opcode, Value *&LHS,
1201e8d8bef9SDimitry Andric                        Value *&RHS) {
1202e8d8bef9SDimitry Andric     if (Opcode == Instruction::And &&
1203e8d8bef9SDimitry Andric         match(I, m_LogicalAnd(m_Value(LHS), m_Value(RHS))))
1204e8d8bef9SDimitry Andric       return true;
1205e8d8bef9SDimitry Andric     else if (Opcode == Instruction::Or &&
1206e8d8bef9SDimitry Andric              match(I, m_LogicalOr(m_Value(LHS), m_Value(RHS))))
1207e8d8bef9SDimitry Andric       return true;
12080b57cec5SDimitry Andric     return false;
12090b57cec5SDimitry Andric   };
12100b57cec5SDimitry Andric   // If the condition is AND operation, we can propagate its operands into the
12110b57cec5SDimitry Andric   // true branch. If it is OR operation, we can propagate them into the false
12120b57cec5SDimitry Andric   // branch.
12130b57cec5SDimitry Andric   unsigned PropagateOpcode =
12140b57cec5SDimitry Andric       (BI->getSuccessor(0) == BB) ? Instruction::And : Instruction::Or;
12150b57cec5SDimitry Andric 
12160b57cec5SDimitry Andric   bool MadeChanges = false;
12170b57cec5SDimitry Andric   SmallVector<Instruction *, 4> WorkList;
12180b57cec5SDimitry Andric   SmallPtrSet<Instruction *, 4> Visited;
12190b57cec5SDimitry Andric   WorkList.push_back(CondInst);
12200b57cec5SDimitry Andric   while (!WorkList.empty()) {
12210b57cec5SDimitry Andric     Instruction *Curr = WorkList.pop_back_val();
12220b57cec5SDimitry Andric 
12230b57cec5SDimitry Andric     AvailableValues.insert(Curr, TorF);
12240b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "EarlyCSE CVP: Add conditional value for '"
12250b57cec5SDimitry Andric                       << Curr->getName() << "' as " << *TorF << " in "
12260b57cec5SDimitry Andric                       << BB->getName() << "\n");
12270b57cec5SDimitry Andric     if (!DebugCounter::shouldExecute(CSECounter)) {
12280b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "Skipping due to debug counter\n");
12290b57cec5SDimitry Andric     } else {
12300b57cec5SDimitry Andric       // Replace all dominated uses with the known value.
12310b57cec5SDimitry Andric       if (unsigned Count = replaceDominatedUsesWith(Curr, TorF, DT,
12320b57cec5SDimitry Andric                                                     BasicBlockEdge(Pred, BB))) {
12330b57cec5SDimitry Andric         NumCSECVP += Count;
12340b57cec5SDimitry Andric         MadeChanges = true;
12350b57cec5SDimitry Andric       }
12360b57cec5SDimitry Andric     }
12370b57cec5SDimitry Andric 
1238e8d8bef9SDimitry Andric     Value *LHS, *RHS;
1239e8d8bef9SDimitry Andric     if (MatchBinOp(Curr, PropagateOpcode, LHS, RHS))
1240bdd1243dSDimitry Andric       for (auto *Op : { LHS, RHS })
12410b57cec5SDimitry Andric         if (Instruction *OPI = dyn_cast<Instruction>(Op))
12420b57cec5SDimitry Andric           if (SimpleValue::canHandle(OPI) && Visited.insert(OPI).second)
12430b57cec5SDimitry Andric             WorkList.push_back(OPI);
12440b57cec5SDimitry Andric   }
12450b57cec5SDimitry Andric 
12460b57cec5SDimitry Andric   return MadeChanges;
12470b57cec5SDimitry Andric }
12480b57cec5SDimitry Andric 
1249e8d8bef9SDimitry Andric Value *EarlyCSE::getMatchingValue(LoadValue &InVal, ParseMemoryInst &MemInst,
1250e8d8bef9SDimitry Andric                                   unsigned CurrentGeneration) {
1251e8d8bef9SDimitry Andric   if (InVal.DefInst == nullptr)
1252e8d8bef9SDimitry Andric     return nullptr;
1253e8d8bef9SDimitry Andric   if (InVal.MatchingId != MemInst.getMatchingId())
1254e8d8bef9SDimitry Andric     return nullptr;
1255e8d8bef9SDimitry Andric   // We don't yet handle removing loads with ordering of any kind.
1256e8d8bef9SDimitry Andric   if (MemInst.isVolatile() || !MemInst.isUnordered())
1257e8d8bef9SDimitry Andric     return nullptr;
1258e8d8bef9SDimitry Andric   // We can't replace an atomic load with one which isn't also atomic.
1259e8d8bef9SDimitry Andric   if (MemInst.isLoad() && !InVal.IsAtomic && MemInst.isAtomic())
1260e8d8bef9SDimitry Andric     return nullptr;
1261e8d8bef9SDimitry Andric   // The value V returned from this function is used differently depending
1262e8d8bef9SDimitry Andric   // on whether MemInst is a load or a store. If it's a load, we will replace
1263e8d8bef9SDimitry Andric   // MemInst with V, if it's a store, we will check if V is the same as the
1264e8d8bef9SDimitry Andric   // available value.
1265e8d8bef9SDimitry Andric   bool MemInstMatching = !MemInst.isLoad();
1266e8d8bef9SDimitry Andric   Instruction *Matching = MemInstMatching ? MemInst.get() : InVal.DefInst;
1267e8d8bef9SDimitry Andric   Instruction *Other = MemInstMatching ? InVal.DefInst : MemInst.get();
1268e8d8bef9SDimitry Andric 
1269e8d8bef9SDimitry Andric   // For stores check the result values before checking memory generation
1270e8d8bef9SDimitry Andric   // (otherwise isSameMemGeneration may crash).
1271e8d8bef9SDimitry Andric   Value *Result = MemInst.isStore()
1272e8d8bef9SDimitry Andric                       ? getOrCreateResult(Matching, Other->getType())
1273e8d8bef9SDimitry Andric                       : nullptr;
1274e8d8bef9SDimitry Andric   if (MemInst.isStore() && InVal.DefInst != Result)
1275e8d8bef9SDimitry Andric     return nullptr;
1276e8d8bef9SDimitry Andric 
1277e8d8bef9SDimitry Andric   // Deal with non-target memory intrinsics.
1278e8d8bef9SDimitry Andric   bool MatchingNTI = isHandledNonTargetIntrinsic(Matching);
1279e8d8bef9SDimitry Andric   bool OtherNTI = isHandledNonTargetIntrinsic(Other);
1280e8d8bef9SDimitry Andric   if (OtherNTI != MatchingNTI)
1281e8d8bef9SDimitry Andric     return nullptr;
1282e8d8bef9SDimitry Andric   if (OtherNTI && MatchingNTI) {
1283e8d8bef9SDimitry Andric     if (!isNonTargetIntrinsicMatch(cast<IntrinsicInst>(InVal.DefInst),
1284e8d8bef9SDimitry Andric                                    cast<IntrinsicInst>(MemInst.get())))
1285e8d8bef9SDimitry Andric       return nullptr;
1286e8d8bef9SDimitry Andric   }
1287e8d8bef9SDimitry Andric 
1288e8d8bef9SDimitry Andric   if (!isOperatingOnInvariantMemAt(MemInst.get(), InVal.Generation) &&
1289e8d8bef9SDimitry Andric       !isSameMemGeneration(InVal.Generation, CurrentGeneration, InVal.DefInst,
1290e8d8bef9SDimitry Andric                            MemInst.get()))
1291e8d8bef9SDimitry Andric     return nullptr;
1292e8d8bef9SDimitry Andric 
1293e8d8bef9SDimitry Andric   if (!Result)
1294e8d8bef9SDimitry Andric     Result = getOrCreateResult(Matching, Other->getType());
1295e8d8bef9SDimitry Andric   return Result;
1296e8d8bef9SDimitry Andric }
1297e8d8bef9SDimitry Andric 
12985f757f3fSDimitry Andric static void combineIRFlags(Instruction &From, Value *To) {
12995f757f3fSDimitry Andric   if (auto *I = dyn_cast<Instruction>(To)) {
13005f757f3fSDimitry Andric     // If I being poison triggers UB, there is no need to drop those
13015f757f3fSDimitry Andric     // flags. Otherwise, only retain flags present on both I and Inst.
13025f757f3fSDimitry Andric     // TODO: Currently some fast-math flags are not treated as
13035f757f3fSDimitry Andric     // poison-generating even though they should. Until this is fixed,
13045f757f3fSDimitry Andric     // always retain flags present on both I and Inst for floating point
13055f757f3fSDimitry Andric     // instructions.
13065f757f3fSDimitry Andric     if (isa<FPMathOperator>(I) ||
13075f757f3fSDimitry Andric         (I->hasPoisonGeneratingFlags() && !programUndefinedIfPoison(I)))
13085f757f3fSDimitry Andric       I->andIRFlags(&From);
13095f757f3fSDimitry Andric   }
13105f757f3fSDimitry Andric }
13115f757f3fSDimitry Andric 
1312e8d8bef9SDimitry Andric bool EarlyCSE::overridingStores(const ParseMemoryInst &Earlier,
1313e8d8bef9SDimitry Andric                                 const ParseMemoryInst &Later) {
1314e8d8bef9SDimitry Andric   // Can we remove Earlier store because of Later store?
1315e8d8bef9SDimitry Andric 
1316e8d8bef9SDimitry Andric   assert(Earlier.isUnordered() && !Earlier.isVolatile() &&
1317e8d8bef9SDimitry Andric          "Violated invariant");
1318e8d8bef9SDimitry Andric   if (Earlier.getPointerOperand() != Later.getPointerOperand())
1319e8d8bef9SDimitry Andric     return false;
132081ad6265SDimitry Andric   if (!Earlier.getValueType() || !Later.getValueType() ||
132181ad6265SDimitry Andric       Earlier.getValueType() != Later.getValueType())
132281ad6265SDimitry Andric     return false;
1323e8d8bef9SDimitry Andric   if (Earlier.getMatchingId() != Later.getMatchingId())
1324e8d8bef9SDimitry Andric     return false;
1325e8d8bef9SDimitry Andric   // At the moment, we don't remove ordered stores, but do remove
1326e8d8bef9SDimitry Andric   // unordered atomic stores.  There's no special requirement (for
1327e8d8bef9SDimitry Andric   // unordered atomics) about removing atomic stores only in favor of
1328e8d8bef9SDimitry Andric   // other atomic stores since we were going to execute the non-atomic
1329e8d8bef9SDimitry Andric   // one anyway and the atomic one might never have become visible.
1330e8d8bef9SDimitry Andric   if (!Earlier.isUnordered() || !Later.isUnordered())
1331e8d8bef9SDimitry Andric     return false;
1332e8d8bef9SDimitry Andric 
1333e8d8bef9SDimitry Andric   // Deal with non-target memory intrinsics.
1334e8d8bef9SDimitry Andric   bool ENTI = isHandledNonTargetIntrinsic(Earlier.get());
1335e8d8bef9SDimitry Andric   bool LNTI = isHandledNonTargetIntrinsic(Later.get());
1336e8d8bef9SDimitry Andric   if (ENTI && LNTI)
1337e8d8bef9SDimitry Andric     return isNonTargetIntrinsicMatch(cast<IntrinsicInst>(Earlier.get()),
1338e8d8bef9SDimitry Andric                                      cast<IntrinsicInst>(Later.get()));
1339e8d8bef9SDimitry Andric 
1340e8d8bef9SDimitry Andric   // Because of the check above, at least one of them is false.
1341e8d8bef9SDimitry Andric   // For now disallow matching intrinsics with non-intrinsics,
1342e8d8bef9SDimitry Andric   // so assume that the stores match if neither is an intrinsic.
1343e8d8bef9SDimitry Andric   return ENTI == LNTI;
1344e8d8bef9SDimitry Andric }
1345e8d8bef9SDimitry Andric 
13460b57cec5SDimitry Andric bool EarlyCSE::processNode(DomTreeNode *Node) {
13470b57cec5SDimitry Andric   bool Changed = false;
13480b57cec5SDimitry Andric   BasicBlock *BB = Node->getBlock();
13490b57cec5SDimitry Andric 
13500b57cec5SDimitry Andric   // If this block has a single predecessor, then the predecessor is the parent
13510b57cec5SDimitry Andric   // of the domtree node and all of the live out memory values are still current
13520b57cec5SDimitry Andric   // in this block.  If this block has multiple predecessors, then they could
13530b57cec5SDimitry Andric   // have invalidated the live-out memory values of our parent value.  For now,
13540b57cec5SDimitry Andric   // just be conservative and invalidate memory if this block has multiple
13550b57cec5SDimitry Andric   // predecessors.
13560b57cec5SDimitry Andric   if (!BB->getSinglePredecessor())
13570b57cec5SDimitry Andric     ++CurrentGeneration;
13580b57cec5SDimitry Andric 
13590b57cec5SDimitry Andric   // If this node has a single predecessor which ends in a conditional branch,
13600b57cec5SDimitry Andric   // we can infer the value of the branch condition given that we took this
13610b57cec5SDimitry Andric   // path.  We need the single predecessor to ensure there's not another path
13620b57cec5SDimitry Andric   // which reaches this block where the condition might hold a different
13630b57cec5SDimitry Andric   // value.  Since we're adding this to the scoped hash table (like any other
13640b57cec5SDimitry Andric   // def), it will have been popped if we encounter a future merge block.
13650b57cec5SDimitry Andric   if (BasicBlock *Pred = BB->getSinglePredecessor()) {
13660b57cec5SDimitry Andric     auto *BI = dyn_cast<BranchInst>(Pred->getTerminator());
13670b57cec5SDimitry Andric     if (BI && BI->isConditional()) {
13680b57cec5SDimitry Andric       auto *CondInst = dyn_cast<Instruction>(BI->getCondition());
13690b57cec5SDimitry Andric       if (CondInst && SimpleValue::canHandle(CondInst))
13700b57cec5SDimitry Andric         Changed |= handleBranchCondition(CondInst, BI, BB, Pred);
13710b57cec5SDimitry Andric     }
13720b57cec5SDimitry Andric   }
13730b57cec5SDimitry Andric 
13740b57cec5SDimitry Andric   /// LastStore - Keep track of the last non-volatile store that we saw... for
13750b57cec5SDimitry Andric   /// as long as there in no instruction that reads memory.  If we see a store
13760b57cec5SDimitry Andric   /// to the same location, we delete the dead store.  This zaps trivial dead
13770b57cec5SDimitry Andric   /// stores which can occur in bitfield code among other things.
13780b57cec5SDimitry Andric   Instruction *LastStore = nullptr;
13790b57cec5SDimitry Andric 
13800b57cec5SDimitry Andric   // See if any instructions in the block can be eliminated.  If so, do it.  If
13810b57cec5SDimitry Andric   // not, add them to AvailableValues.
1382bdd1243dSDimitry Andric   for (Instruction &Inst : make_early_inc_range(*BB)) {
13830b57cec5SDimitry Andric     // Dead instructions should just be removed.
13845ffd83dbSDimitry Andric     if (isInstructionTriviallyDead(&Inst, &TLI)) {
13855ffd83dbSDimitry Andric       LLVM_DEBUG(dbgs() << "EarlyCSE DCE: " << Inst << '\n');
13860b57cec5SDimitry Andric       if (!DebugCounter::shouldExecute(CSECounter)) {
13870b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "Skipping due to debug counter\n");
13880b57cec5SDimitry Andric         continue;
13890b57cec5SDimitry Andric       }
1390480093f4SDimitry Andric 
13915ffd83dbSDimitry Andric       salvageKnowledge(&Inst, &AC);
13925ffd83dbSDimitry Andric       salvageDebugInfo(Inst);
13930b57cec5SDimitry Andric       removeMSSA(Inst);
13945ffd83dbSDimitry Andric       Inst.eraseFromParent();
13950b57cec5SDimitry Andric       Changed = true;
13960b57cec5SDimitry Andric       ++NumSimplify;
13970b57cec5SDimitry Andric       continue;
13980b57cec5SDimitry Andric     }
13990b57cec5SDimitry Andric 
14000b57cec5SDimitry Andric     // Skip assume intrinsics, they don't really have side effects (although
14010b57cec5SDimitry Andric     // they're marked as such to ensure preservation of control dependencies),
14020b57cec5SDimitry Andric     // and this pass will not bother with its removal. However, we should mark
14030b57cec5SDimitry Andric     // its condition as true for all dominated blocks.
1404fe6060f1SDimitry Andric     if (auto *Assume = dyn_cast<AssumeInst>(&Inst)) {
1405fe6060f1SDimitry Andric       auto *CondI = dyn_cast<Instruction>(Assume->getArgOperand(0));
14060b57cec5SDimitry Andric       if (CondI && SimpleValue::canHandle(CondI)) {
14075ffd83dbSDimitry Andric         LLVM_DEBUG(dbgs() << "EarlyCSE considering assumption: " << Inst
14080b57cec5SDimitry Andric                           << '\n');
14090b57cec5SDimitry Andric         AvailableValues.insert(CondI, ConstantInt::getTrue(BB->getContext()));
14100b57cec5SDimitry Andric       } else
14115ffd83dbSDimitry Andric         LLVM_DEBUG(dbgs() << "EarlyCSE skipping assumption: " << Inst << '\n');
14120b57cec5SDimitry Andric       continue;
14130b57cec5SDimitry Andric     }
14140b57cec5SDimitry Andric 
1415e8d8bef9SDimitry Andric     // Likewise, noalias intrinsics don't actually write.
1416e8d8bef9SDimitry Andric     if (match(&Inst,
1417e8d8bef9SDimitry Andric               m_Intrinsic<Intrinsic::experimental_noalias_scope_decl>())) {
1418e8d8bef9SDimitry Andric       LLVM_DEBUG(dbgs() << "EarlyCSE skipping noalias intrinsic: " << Inst
1419e8d8bef9SDimitry Andric                         << '\n');
1420e8d8bef9SDimitry Andric       continue;
1421e8d8bef9SDimitry Andric     }
1422e8d8bef9SDimitry Andric 
14230b57cec5SDimitry Andric     // Skip sideeffect intrinsics, for the same reason as assume intrinsics.
14245ffd83dbSDimitry Andric     if (match(&Inst, m_Intrinsic<Intrinsic::sideeffect>())) {
14255ffd83dbSDimitry Andric       LLVM_DEBUG(dbgs() << "EarlyCSE skipping sideeffect: " << Inst << '\n');
14260b57cec5SDimitry Andric       continue;
14270b57cec5SDimitry Andric     }
14280b57cec5SDimitry Andric 
1429349cc55cSDimitry Andric     // Skip pseudoprobe intrinsics, for the same reason as assume intrinsics.
1430349cc55cSDimitry Andric     if (match(&Inst, m_Intrinsic<Intrinsic::pseudoprobe>())) {
1431349cc55cSDimitry Andric       LLVM_DEBUG(dbgs() << "EarlyCSE skipping pseudoprobe: " << Inst << '\n');
1432349cc55cSDimitry Andric       continue;
1433349cc55cSDimitry Andric     }
1434349cc55cSDimitry Andric 
14350b57cec5SDimitry Andric     // We can skip all invariant.start intrinsics since they only read memory,
14360b57cec5SDimitry Andric     // and we can forward values across it. For invariant starts without
14370b57cec5SDimitry Andric     // invariant ends, we can use the fact that the invariantness never ends to
14380b57cec5SDimitry Andric     // start a scope in the current generaton which is true for all future
14390b57cec5SDimitry Andric     // generations.  Also, we dont need to consume the last store since the
14400b57cec5SDimitry Andric     // semantics of invariant.start allow us to perform   DSE of the last
14410b57cec5SDimitry Andric     // store, if there was a store following invariant.start. Consider:
14420b57cec5SDimitry Andric     //
14430b57cec5SDimitry Andric     // store 30, i8* p
14440b57cec5SDimitry Andric     // invariant.start(p)
14450b57cec5SDimitry Andric     // store 40, i8* p
14460b57cec5SDimitry Andric     // We can DSE the store to 30, since the store 40 to invariant location p
14470b57cec5SDimitry Andric     // causes undefined behaviour.
14485ffd83dbSDimitry Andric     if (match(&Inst, m_Intrinsic<Intrinsic::invariant_start>())) {
14490b57cec5SDimitry Andric       // If there are any uses, the scope might end.
14505ffd83dbSDimitry Andric       if (!Inst.use_empty())
14510b57cec5SDimitry Andric         continue;
14525ffd83dbSDimitry Andric       MemoryLocation MemLoc =
14535ffd83dbSDimitry Andric           MemoryLocation::getForArgument(&cast<CallInst>(Inst), 1, TLI);
14540b57cec5SDimitry Andric       // Don't start a scope if we already have a better one pushed
14550b57cec5SDimitry Andric       if (!AvailableInvariants.count(MemLoc))
14560b57cec5SDimitry Andric         AvailableInvariants.insert(MemLoc, CurrentGeneration);
14570b57cec5SDimitry Andric       continue;
14580b57cec5SDimitry Andric     }
14590b57cec5SDimitry Andric 
14605ffd83dbSDimitry Andric     if (isGuard(&Inst)) {
14610b57cec5SDimitry Andric       if (auto *CondI =
14625ffd83dbSDimitry Andric               dyn_cast<Instruction>(cast<CallInst>(Inst).getArgOperand(0))) {
14630b57cec5SDimitry Andric         if (SimpleValue::canHandle(CondI)) {
14640b57cec5SDimitry Andric           // Do we already know the actual value of this condition?
14650b57cec5SDimitry Andric           if (auto *KnownCond = AvailableValues.lookup(CondI)) {
14660b57cec5SDimitry Andric             // Is the condition known to be true?
14670b57cec5SDimitry Andric             if (isa<ConstantInt>(KnownCond) &&
14680b57cec5SDimitry Andric                 cast<ConstantInt>(KnownCond)->isOne()) {
14690b57cec5SDimitry Andric               LLVM_DEBUG(dbgs()
14705ffd83dbSDimitry Andric                          << "EarlyCSE removing guard: " << Inst << '\n');
14715ffd83dbSDimitry Andric               salvageKnowledge(&Inst, &AC);
14720b57cec5SDimitry Andric               removeMSSA(Inst);
14735ffd83dbSDimitry Andric               Inst.eraseFromParent();
14740b57cec5SDimitry Andric               Changed = true;
14750b57cec5SDimitry Andric               continue;
14760b57cec5SDimitry Andric             } else
14770b57cec5SDimitry Andric               // Use the known value if it wasn't true.
14785ffd83dbSDimitry Andric               cast<CallInst>(Inst).setArgOperand(0, KnownCond);
14790b57cec5SDimitry Andric           }
14800b57cec5SDimitry Andric           // The condition we're on guarding here is true for all dominated
14810b57cec5SDimitry Andric           // locations.
14820b57cec5SDimitry Andric           AvailableValues.insert(CondI, ConstantInt::getTrue(BB->getContext()));
14830b57cec5SDimitry Andric         }
14840b57cec5SDimitry Andric       }
14850b57cec5SDimitry Andric 
14860b57cec5SDimitry Andric       // Guard intrinsics read all memory, but don't write any memory.
14870b57cec5SDimitry Andric       // Accordingly, don't update the generation but consume the last store (to
14880b57cec5SDimitry Andric       // avoid an incorrect DSE).
14890b57cec5SDimitry Andric       LastStore = nullptr;
14900b57cec5SDimitry Andric       continue;
14910b57cec5SDimitry Andric     }
14920b57cec5SDimitry Andric 
14930b57cec5SDimitry Andric     // If the instruction can be simplified (e.g. X+0 = X) then replace it with
14940b57cec5SDimitry Andric     // its simpler value.
149581ad6265SDimitry Andric     if (Value *V = simplifyInstruction(&Inst, SQ)) {
14965ffd83dbSDimitry Andric       LLVM_DEBUG(dbgs() << "EarlyCSE Simplify: " << Inst << "  to: " << *V
14970b57cec5SDimitry Andric                         << '\n');
14980b57cec5SDimitry Andric       if (!DebugCounter::shouldExecute(CSECounter)) {
14990b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "Skipping due to debug counter\n");
15000b57cec5SDimitry Andric       } else {
15010b57cec5SDimitry Andric         bool Killed = false;
15025ffd83dbSDimitry Andric         if (!Inst.use_empty()) {
15035ffd83dbSDimitry Andric           Inst.replaceAllUsesWith(V);
15040b57cec5SDimitry Andric           Changed = true;
15050b57cec5SDimitry Andric         }
15065ffd83dbSDimitry Andric         if (isInstructionTriviallyDead(&Inst, &TLI)) {
15075ffd83dbSDimitry Andric           salvageKnowledge(&Inst, &AC);
15080b57cec5SDimitry Andric           removeMSSA(Inst);
15095ffd83dbSDimitry Andric           Inst.eraseFromParent();
15100b57cec5SDimitry Andric           Changed = true;
15110b57cec5SDimitry Andric           Killed = true;
15120b57cec5SDimitry Andric         }
15130b57cec5SDimitry Andric         if (Changed)
15140b57cec5SDimitry Andric           ++NumSimplify;
15150b57cec5SDimitry Andric         if (Killed)
15160b57cec5SDimitry Andric           continue;
15170b57cec5SDimitry Andric       }
15180b57cec5SDimitry Andric     }
15190b57cec5SDimitry Andric 
15200b57cec5SDimitry Andric     // If this is a simple instruction that we can value number, process it.
15215ffd83dbSDimitry Andric     if (SimpleValue::canHandle(&Inst)) {
15225f757f3fSDimitry Andric       if ([[maybe_unused]] auto *CI = dyn_cast<ConstrainedFPIntrinsic>(&Inst)) {
1523bdd1243dSDimitry Andric         assert(CI->getExceptionBehavior() != fp::ebStrict &&
1524bdd1243dSDimitry Andric                "Unexpected ebStrict from SimpleValue::canHandle()");
1525bdd1243dSDimitry Andric         assert((!CI->getRoundingMode() ||
1526bdd1243dSDimitry Andric                 CI->getRoundingMode() != RoundingMode::Dynamic) &&
1527bdd1243dSDimitry Andric                "Unexpected dynamic rounding from SimpleValue::canHandle()");
1528bdd1243dSDimitry Andric       }
15290b57cec5SDimitry Andric       // See if the instruction has an available value.  If so, use it.
15305ffd83dbSDimitry Andric       if (Value *V = AvailableValues.lookup(&Inst)) {
15315ffd83dbSDimitry Andric         LLVM_DEBUG(dbgs() << "EarlyCSE CSE: " << Inst << "  to: " << *V
15320b57cec5SDimitry Andric                           << '\n');
15330b57cec5SDimitry Andric         if (!DebugCounter::shouldExecute(CSECounter)) {
15340b57cec5SDimitry Andric           LLVM_DEBUG(dbgs() << "Skipping due to debug counter\n");
15350b57cec5SDimitry Andric           continue;
15360b57cec5SDimitry Andric         }
15375f757f3fSDimitry Andric         combineIRFlags(Inst, V);
15385ffd83dbSDimitry Andric         Inst.replaceAllUsesWith(V);
15395ffd83dbSDimitry Andric         salvageKnowledge(&Inst, &AC);
15400b57cec5SDimitry Andric         removeMSSA(Inst);
15415ffd83dbSDimitry Andric         Inst.eraseFromParent();
15420b57cec5SDimitry Andric         Changed = true;
15430b57cec5SDimitry Andric         ++NumCSE;
15440b57cec5SDimitry Andric         continue;
15450b57cec5SDimitry Andric       }
15460b57cec5SDimitry Andric 
15470b57cec5SDimitry Andric       // Otherwise, just remember that this value is available.
15485ffd83dbSDimitry Andric       AvailableValues.insert(&Inst, &Inst);
15490b57cec5SDimitry Andric       continue;
15500b57cec5SDimitry Andric     }
15510b57cec5SDimitry Andric 
15525ffd83dbSDimitry Andric     ParseMemoryInst MemInst(&Inst, TTI);
15530b57cec5SDimitry Andric     // If this is a non-volatile load, process it.
15540b57cec5SDimitry Andric     if (MemInst.isValid() && MemInst.isLoad()) {
15550b57cec5SDimitry Andric       // (conservatively) we can't peak past the ordering implied by this
15560b57cec5SDimitry Andric       // operation, but we can add this load to our set of available values
15570b57cec5SDimitry Andric       if (MemInst.isVolatile() || !MemInst.isUnordered()) {
15580b57cec5SDimitry Andric         LastStore = nullptr;
15590b57cec5SDimitry Andric         ++CurrentGeneration;
15600b57cec5SDimitry Andric       }
15610b57cec5SDimitry Andric 
15620b57cec5SDimitry Andric       if (MemInst.isInvariantLoad()) {
15630b57cec5SDimitry Andric         // If we pass an invariant load, we know that memory location is
15640b57cec5SDimitry Andric         // indefinitely constant from the moment of first dereferenceability.
15650b57cec5SDimitry Andric         // We conservatively treat the invariant_load as that moment.  If we
15660b57cec5SDimitry Andric         // pass a invariant load after already establishing a scope, don't
15670b57cec5SDimitry Andric         // restart it since we want to preserve the earliest point seen.
15685ffd83dbSDimitry Andric         auto MemLoc = MemoryLocation::get(&Inst);
15690b57cec5SDimitry Andric         if (!AvailableInvariants.count(MemLoc))
15700b57cec5SDimitry Andric           AvailableInvariants.insert(MemLoc, CurrentGeneration);
15710b57cec5SDimitry Andric       }
15720b57cec5SDimitry Andric 
15730b57cec5SDimitry Andric       // If we have an available version of this load, and if it is the right
15740b57cec5SDimitry Andric       // generation or the load is known to be from an invariant location,
15750b57cec5SDimitry Andric       // replace this instruction.
15760b57cec5SDimitry Andric       //
15770b57cec5SDimitry Andric       // If either the dominating load or the current load are invariant, then
15780b57cec5SDimitry Andric       // we can assume the current load loads the same value as the dominating
15790b57cec5SDimitry Andric       // load.
15800b57cec5SDimitry Andric       LoadValue InVal = AvailableLoads.lookup(MemInst.getPointerOperand());
1581e8d8bef9SDimitry Andric       if (Value *Op = getMatchingValue(InVal, MemInst, CurrentGeneration)) {
15825ffd83dbSDimitry Andric         LLVM_DEBUG(dbgs() << "EarlyCSE CSE LOAD: " << Inst
15830b57cec5SDimitry Andric                           << "  to: " << *InVal.DefInst << '\n');
15840b57cec5SDimitry Andric         if (!DebugCounter::shouldExecute(CSECounter)) {
15850b57cec5SDimitry Andric           LLVM_DEBUG(dbgs() << "Skipping due to debug counter\n");
15860b57cec5SDimitry Andric           continue;
15870b57cec5SDimitry Andric         }
158806c3fb27SDimitry Andric         if (InVal.IsLoad)
158906c3fb27SDimitry Andric           if (auto *I = dyn_cast<Instruction>(Op))
159006c3fb27SDimitry Andric             combineMetadataForCSE(I, &Inst, false);
15915ffd83dbSDimitry Andric         if (!Inst.use_empty())
15925ffd83dbSDimitry Andric           Inst.replaceAllUsesWith(Op);
15935ffd83dbSDimitry Andric         salvageKnowledge(&Inst, &AC);
15940b57cec5SDimitry Andric         removeMSSA(Inst);
15955ffd83dbSDimitry Andric         Inst.eraseFromParent();
15960b57cec5SDimitry Andric         Changed = true;
15970b57cec5SDimitry Andric         ++NumCSELoad;
15980b57cec5SDimitry Andric         continue;
15990b57cec5SDimitry Andric       }
16000b57cec5SDimitry Andric 
16010b57cec5SDimitry Andric       // Otherwise, remember that we have this instruction.
16025ffd83dbSDimitry Andric       AvailableLoads.insert(MemInst.getPointerOperand(),
16035ffd83dbSDimitry Andric                             LoadValue(&Inst, CurrentGeneration,
16045ffd83dbSDimitry Andric                                       MemInst.getMatchingId(),
160506c3fb27SDimitry Andric                                       MemInst.isAtomic(),
160606c3fb27SDimitry Andric                                       MemInst.isLoad()));
16070b57cec5SDimitry Andric       LastStore = nullptr;
16080b57cec5SDimitry Andric       continue;
16090b57cec5SDimitry Andric     }
16100b57cec5SDimitry Andric 
16110b57cec5SDimitry Andric     // If this instruction may read from memory or throw (and potentially read
16120b57cec5SDimitry Andric     // from memory in the exception handler), forget LastStore.  Load/store
16130b57cec5SDimitry Andric     // intrinsics will indicate both a read and a write to memory.  The target
16140b57cec5SDimitry Andric     // may override this (e.g. so that a store intrinsic does not read from
16150b57cec5SDimitry Andric     // memory, and thus will be treated the same as a regular store for
16160b57cec5SDimitry Andric     // commoning purposes).
16175ffd83dbSDimitry Andric     if ((Inst.mayReadFromMemory() || Inst.mayThrow()) &&
16180b57cec5SDimitry Andric         !(MemInst.isValid() && !MemInst.mayReadFromMemory()))
16190b57cec5SDimitry Andric       LastStore = nullptr;
16200b57cec5SDimitry Andric 
16210b57cec5SDimitry Andric     // If this is a read-only call, process it.
16225ffd83dbSDimitry Andric     if (CallValue::canHandle(&Inst)) {
16230b57cec5SDimitry Andric       // If we have an available version of this call, and if it is the right
16240b57cec5SDimitry Andric       // generation, replace this instruction.
16255ffd83dbSDimitry Andric       std::pair<Instruction *, unsigned> InVal = AvailableCalls.lookup(&Inst);
16260b57cec5SDimitry Andric       if (InVal.first != nullptr &&
16270b57cec5SDimitry Andric           isSameMemGeneration(InVal.second, CurrentGeneration, InVal.first,
16285ffd83dbSDimitry Andric                               &Inst)) {
16295ffd83dbSDimitry Andric         LLVM_DEBUG(dbgs() << "EarlyCSE CSE CALL: " << Inst
16300b57cec5SDimitry Andric                           << "  to: " << *InVal.first << '\n');
16310b57cec5SDimitry Andric         if (!DebugCounter::shouldExecute(CSECounter)) {
16320b57cec5SDimitry Andric           LLVM_DEBUG(dbgs() << "Skipping due to debug counter\n");
16330b57cec5SDimitry Andric           continue;
16340b57cec5SDimitry Andric         }
16355ffd83dbSDimitry Andric         if (!Inst.use_empty())
16365ffd83dbSDimitry Andric           Inst.replaceAllUsesWith(InVal.first);
16375ffd83dbSDimitry Andric         salvageKnowledge(&Inst, &AC);
16380b57cec5SDimitry Andric         removeMSSA(Inst);
16395ffd83dbSDimitry Andric         Inst.eraseFromParent();
16400b57cec5SDimitry Andric         Changed = true;
16410b57cec5SDimitry Andric         ++NumCSECall;
16420b57cec5SDimitry Andric         continue;
16430b57cec5SDimitry Andric       }
16440b57cec5SDimitry Andric 
16450b57cec5SDimitry Andric       // Otherwise, remember that we have this instruction.
16465ffd83dbSDimitry Andric       AvailableCalls.insert(&Inst, std::make_pair(&Inst, CurrentGeneration));
16470b57cec5SDimitry Andric       continue;
16480b57cec5SDimitry Andric     }
16490b57cec5SDimitry Andric 
16505f757f3fSDimitry Andric     // Compare GEP instructions based on offset.
16515f757f3fSDimitry Andric     if (GEPValue::canHandle(&Inst)) {
16525f757f3fSDimitry Andric       auto *GEP = cast<GetElementPtrInst>(&Inst);
16535f757f3fSDimitry Andric       APInt Offset = APInt(SQ.DL.getIndexTypeSizeInBits(GEP->getType()), 0);
16545f757f3fSDimitry Andric       GEPValue GEPVal(GEP, GEP->accumulateConstantOffset(SQ.DL, Offset)
16555f757f3fSDimitry Andric                                ? Offset.trySExtValue()
16565f757f3fSDimitry Andric                                : std::nullopt);
16575f757f3fSDimitry Andric       if (Value *V = AvailableGEPs.lookup(GEPVal)) {
16585f757f3fSDimitry Andric         LLVM_DEBUG(dbgs() << "EarlyCSE CSE GEP: " << Inst << "  to: " << *V
16595f757f3fSDimitry Andric                           << '\n');
16605f757f3fSDimitry Andric         combineIRFlags(Inst, V);
16615f757f3fSDimitry Andric         Inst.replaceAllUsesWith(V);
16625f757f3fSDimitry Andric         salvageKnowledge(&Inst, &AC);
16635f757f3fSDimitry Andric         removeMSSA(Inst);
16645f757f3fSDimitry Andric         Inst.eraseFromParent();
16655f757f3fSDimitry Andric         Changed = true;
16665f757f3fSDimitry Andric         ++NumCSEGEP;
16675f757f3fSDimitry Andric         continue;
16685f757f3fSDimitry Andric       }
16695f757f3fSDimitry Andric 
16705f757f3fSDimitry Andric       // Otherwise, just remember that we have this GEP.
16715f757f3fSDimitry Andric       AvailableGEPs.insert(GEPVal, &Inst);
16725f757f3fSDimitry Andric       continue;
16735f757f3fSDimitry Andric     }
16745f757f3fSDimitry Andric 
16750b57cec5SDimitry Andric     // A release fence requires that all stores complete before it, but does
16760b57cec5SDimitry Andric     // not prevent the reordering of following loads 'before' the fence.  As a
16770b57cec5SDimitry Andric     // result, we don't need to consider it as writing to memory and don't need
16780b57cec5SDimitry Andric     // to advance the generation.  We do need to prevent DSE across the fence,
16790b57cec5SDimitry Andric     // but that's handled above.
16805ffd83dbSDimitry Andric     if (auto *FI = dyn_cast<FenceInst>(&Inst))
16810b57cec5SDimitry Andric       if (FI->getOrdering() == AtomicOrdering::Release) {
16825ffd83dbSDimitry Andric         assert(Inst.mayReadFromMemory() && "relied on to prevent DSE above");
16830b57cec5SDimitry Andric         continue;
16840b57cec5SDimitry Andric       }
16850b57cec5SDimitry Andric 
16860b57cec5SDimitry Andric     // write back DSE - If we write back the same value we just loaded from
16870b57cec5SDimitry Andric     // the same location and haven't passed any intervening writes or ordering
16880b57cec5SDimitry Andric     // operations, we can remove the write.  The primary benefit is in allowing
16890b57cec5SDimitry Andric     // the available load table to remain valid and value forward past where
16900b57cec5SDimitry Andric     // the store originally was.
16910b57cec5SDimitry Andric     if (MemInst.isValid() && MemInst.isStore()) {
16920b57cec5SDimitry Andric       LoadValue InVal = AvailableLoads.lookup(MemInst.getPointerOperand());
16930b57cec5SDimitry Andric       if (InVal.DefInst &&
1694e8d8bef9SDimitry Andric           InVal.DefInst == getMatchingValue(InVal, MemInst, CurrentGeneration)) {
16950b57cec5SDimitry Andric         // It is okay to have a LastStore to a different pointer here if MemorySSA
16960b57cec5SDimitry Andric         // tells us that the load and store are from the same memory generation.
16970b57cec5SDimitry Andric         // In that case, LastStore should keep its present value since we're
16980b57cec5SDimitry Andric         // removing the current store.
16990b57cec5SDimitry Andric         assert((!LastStore ||
17000b57cec5SDimitry Andric                 ParseMemoryInst(LastStore, TTI).getPointerOperand() ==
17010b57cec5SDimitry Andric                     MemInst.getPointerOperand() ||
17020b57cec5SDimitry Andric                 MSSA) &&
17030b57cec5SDimitry Andric                "can't have an intervening store if not using MemorySSA!");
17045ffd83dbSDimitry Andric         LLVM_DEBUG(dbgs() << "EarlyCSE DSE (writeback): " << Inst << '\n');
17050b57cec5SDimitry Andric         if (!DebugCounter::shouldExecute(CSECounter)) {
17060b57cec5SDimitry Andric           LLVM_DEBUG(dbgs() << "Skipping due to debug counter\n");
17070b57cec5SDimitry Andric           continue;
17080b57cec5SDimitry Andric         }
17095ffd83dbSDimitry Andric         salvageKnowledge(&Inst, &AC);
17100b57cec5SDimitry Andric         removeMSSA(Inst);
17115ffd83dbSDimitry Andric         Inst.eraseFromParent();
17120b57cec5SDimitry Andric         Changed = true;
17130b57cec5SDimitry Andric         ++NumDSE;
17140b57cec5SDimitry Andric         // We can avoid incrementing the generation count since we were able
17150b57cec5SDimitry Andric         // to eliminate this store.
17160b57cec5SDimitry Andric         continue;
17170b57cec5SDimitry Andric       }
17180b57cec5SDimitry Andric     }
17190b57cec5SDimitry Andric 
17200b57cec5SDimitry Andric     // Okay, this isn't something we can CSE at all.  Check to see if it is
17210b57cec5SDimitry Andric     // something that could modify memory.  If so, our available memory values
17220b57cec5SDimitry Andric     // cannot be used so bump the generation count.
17235ffd83dbSDimitry Andric     if (Inst.mayWriteToMemory()) {
17240b57cec5SDimitry Andric       ++CurrentGeneration;
17250b57cec5SDimitry Andric 
17260b57cec5SDimitry Andric       if (MemInst.isValid() && MemInst.isStore()) {
17270b57cec5SDimitry Andric         // We do a trivial form of DSE if there are two stores to the same
17280b57cec5SDimitry Andric         // location with no intervening loads.  Delete the earlier store.
17290b57cec5SDimitry Andric         if (LastStore) {
1730e8d8bef9SDimitry Andric           if (overridingStores(ParseMemoryInst(LastStore, TTI), MemInst)) {
17310b57cec5SDimitry Andric             LLVM_DEBUG(dbgs() << "EarlyCSE DEAD STORE: " << *LastStore
17325ffd83dbSDimitry Andric                               << "  due to: " << Inst << '\n');
17330b57cec5SDimitry Andric             if (!DebugCounter::shouldExecute(CSECounter)) {
17340b57cec5SDimitry Andric               LLVM_DEBUG(dbgs() << "Skipping due to debug counter\n");
17350b57cec5SDimitry Andric             } else {
17365ffd83dbSDimitry Andric               salvageKnowledge(&Inst, &AC);
17375ffd83dbSDimitry Andric               removeMSSA(*LastStore);
17380b57cec5SDimitry Andric               LastStore->eraseFromParent();
17390b57cec5SDimitry Andric               Changed = true;
17400b57cec5SDimitry Andric               ++NumDSE;
17410b57cec5SDimitry Andric               LastStore = nullptr;
17420b57cec5SDimitry Andric             }
17430b57cec5SDimitry Andric           }
17440b57cec5SDimitry Andric           // fallthrough - we can exploit information about this store
17450b57cec5SDimitry Andric         }
17460b57cec5SDimitry Andric 
17470b57cec5SDimitry Andric         // Okay, we just invalidated anything we knew about loaded values.  Try
17480b57cec5SDimitry Andric         // to salvage *something* by remembering that the stored value is a live
17490b57cec5SDimitry Andric         // version of the pointer.  It is safe to forward from volatile stores
17500b57cec5SDimitry Andric         // to non-volatile loads, so we don't have to check for volatility of
17510b57cec5SDimitry Andric         // the store.
17525ffd83dbSDimitry Andric         AvailableLoads.insert(MemInst.getPointerOperand(),
17535ffd83dbSDimitry Andric                               LoadValue(&Inst, CurrentGeneration,
17545ffd83dbSDimitry Andric                                         MemInst.getMatchingId(),
175506c3fb27SDimitry Andric                                         MemInst.isAtomic(),
175606c3fb27SDimitry Andric                                         MemInst.isLoad()));
17570b57cec5SDimitry Andric 
17580b57cec5SDimitry Andric         // Remember that this was the last unordered store we saw for DSE. We
17590b57cec5SDimitry Andric         // don't yet handle DSE on ordered or volatile stores since we don't
17600b57cec5SDimitry Andric         // have a good way to model the ordering requirement for following
17610b57cec5SDimitry Andric         // passes  once the store is removed.  We could insert a fence, but
17620b57cec5SDimitry Andric         // since fences are slightly stronger than stores in their ordering,
17630b57cec5SDimitry Andric         // it's not clear this is a profitable transform. Another option would
17640b57cec5SDimitry Andric         // be to merge the ordering with that of the post dominating store.
17650b57cec5SDimitry Andric         if (MemInst.isUnordered() && !MemInst.isVolatile())
17665ffd83dbSDimitry Andric           LastStore = &Inst;
17670b57cec5SDimitry Andric         else
17680b57cec5SDimitry Andric           LastStore = nullptr;
17690b57cec5SDimitry Andric       }
17700b57cec5SDimitry Andric     }
17710b57cec5SDimitry Andric   }
17720b57cec5SDimitry Andric 
17730b57cec5SDimitry Andric   return Changed;
17740b57cec5SDimitry Andric }
17750b57cec5SDimitry Andric 
17760b57cec5SDimitry Andric bool EarlyCSE::run() {
17770b57cec5SDimitry Andric   // Note, deque is being used here because there is significant performance
17780b57cec5SDimitry Andric   // gains over vector when the container becomes very large due to the
17790b57cec5SDimitry Andric   // specific access patterns. For more information see the mailing list
17800b57cec5SDimitry Andric   // discussion on this:
17810b57cec5SDimitry Andric   // http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20120116/135228.html
17820b57cec5SDimitry Andric   std::deque<StackNode *> nodesToProcess;
17830b57cec5SDimitry Andric 
17840b57cec5SDimitry Andric   bool Changed = false;
17850b57cec5SDimitry Andric 
17860b57cec5SDimitry Andric   // Process the root node.
17870b57cec5SDimitry Andric   nodesToProcess.push_back(new StackNode(
17880b57cec5SDimitry Andric       AvailableValues, AvailableLoads, AvailableInvariants, AvailableCalls,
17895f757f3fSDimitry Andric       AvailableGEPs, CurrentGeneration, DT.getRootNode(),
17900b57cec5SDimitry Andric       DT.getRootNode()->begin(), DT.getRootNode()->end()));
17910b57cec5SDimitry Andric 
17920b57cec5SDimitry Andric   assert(!CurrentGeneration && "Create a new EarlyCSE instance to rerun it.");
17930b57cec5SDimitry Andric 
17940b57cec5SDimitry Andric   // Process the stack.
17950b57cec5SDimitry Andric   while (!nodesToProcess.empty()) {
17960b57cec5SDimitry Andric     // Grab the first item off the stack. Set the current generation, remove
17970b57cec5SDimitry Andric     // the node from the stack, and process it.
17980b57cec5SDimitry Andric     StackNode *NodeToProcess = nodesToProcess.back();
17990b57cec5SDimitry Andric 
18000b57cec5SDimitry Andric     // Initialize class members.
18010b57cec5SDimitry Andric     CurrentGeneration = NodeToProcess->currentGeneration();
18020b57cec5SDimitry Andric 
18030b57cec5SDimitry Andric     // Check if the node needs to be processed.
18040b57cec5SDimitry Andric     if (!NodeToProcess->isProcessed()) {
18050b57cec5SDimitry Andric       // Process the node.
18060b57cec5SDimitry Andric       Changed |= processNode(NodeToProcess->node());
18070b57cec5SDimitry Andric       NodeToProcess->childGeneration(CurrentGeneration);
18080b57cec5SDimitry Andric       NodeToProcess->process();
18090b57cec5SDimitry Andric     } else if (NodeToProcess->childIter() != NodeToProcess->end()) {
18100b57cec5SDimitry Andric       // Push the next child onto the stack.
18110b57cec5SDimitry Andric       DomTreeNode *child = NodeToProcess->nextChild();
18125f757f3fSDimitry Andric       nodesToProcess.push_back(new StackNode(
18135f757f3fSDimitry Andric           AvailableValues, AvailableLoads, AvailableInvariants, AvailableCalls,
18145f757f3fSDimitry Andric           AvailableGEPs, NodeToProcess->childGeneration(), child,
18155f757f3fSDimitry Andric           child->begin(), child->end()));
18160b57cec5SDimitry Andric     } else {
18170b57cec5SDimitry Andric       // It has been processed, and there are no more children to process,
18180b57cec5SDimitry Andric       // so delete it and pop it off the stack.
18190b57cec5SDimitry Andric       delete NodeToProcess;
18200b57cec5SDimitry Andric       nodesToProcess.pop_back();
18210b57cec5SDimitry Andric     }
18220b57cec5SDimitry Andric   } // while (!nodes...)
18230b57cec5SDimitry Andric 
18240b57cec5SDimitry Andric   return Changed;
18250b57cec5SDimitry Andric }
18260b57cec5SDimitry Andric 
18270b57cec5SDimitry Andric PreservedAnalyses EarlyCSEPass::run(Function &F,
18280b57cec5SDimitry Andric                                     FunctionAnalysisManager &AM) {
18290b57cec5SDimitry Andric   auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
18300b57cec5SDimitry Andric   auto &TTI = AM.getResult<TargetIRAnalysis>(F);
18310b57cec5SDimitry Andric   auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
18320b57cec5SDimitry Andric   auto &AC = AM.getResult<AssumptionAnalysis>(F);
18330b57cec5SDimitry Andric   auto *MSSA =
18340b57cec5SDimitry Andric       UseMemorySSA ? &AM.getResult<MemorySSAAnalysis>(F).getMSSA() : nullptr;
18350b57cec5SDimitry Andric 
1836*0fca6ea1SDimitry Andric   EarlyCSE CSE(F.getDataLayout(), TLI, TTI, DT, AC, MSSA);
18370b57cec5SDimitry Andric 
18380b57cec5SDimitry Andric   if (!CSE.run())
18390b57cec5SDimitry Andric     return PreservedAnalyses::all();
18400b57cec5SDimitry Andric 
18410b57cec5SDimitry Andric   PreservedAnalyses PA;
18420b57cec5SDimitry Andric   PA.preserveSet<CFGAnalyses>();
18430b57cec5SDimitry Andric   if (UseMemorySSA)
18440b57cec5SDimitry Andric     PA.preserve<MemorySSAAnalysis>();
18450b57cec5SDimitry Andric   return PA;
18460b57cec5SDimitry Andric }
18470b57cec5SDimitry Andric 
1848349cc55cSDimitry Andric void EarlyCSEPass::printPipeline(
1849349cc55cSDimitry Andric     raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
1850349cc55cSDimitry Andric   static_cast<PassInfoMixin<EarlyCSEPass> *>(this)->printPipeline(
1851349cc55cSDimitry Andric       OS, MapClassName2PassName);
185206c3fb27SDimitry Andric   OS << '<';
1853349cc55cSDimitry Andric   if (UseMemorySSA)
1854349cc55cSDimitry Andric     OS << "memssa";
185506c3fb27SDimitry Andric   OS << '>';
1856349cc55cSDimitry Andric }
1857349cc55cSDimitry Andric 
18580b57cec5SDimitry Andric namespace {
18590b57cec5SDimitry Andric 
18600b57cec5SDimitry Andric /// A simple and fast domtree-based CSE pass.
18610b57cec5SDimitry Andric ///
18620b57cec5SDimitry Andric /// This pass does a simple depth-first walk over the dominator tree,
18630b57cec5SDimitry Andric /// eliminating trivially redundant instructions and using instsimplify to
18640b57cec5SDimitry Andric /// canonicalize things as it goes. It is intended to be fast and catch obvious
18650b57cec5SDimitry Andric /// cases so that instcombine and other passes are more effective. It is
18660b57cec5SDimitry Andric /// expected that a later pass of GVN will catch the interesting/hard cases.
18670b57cec5SDimitry Andric template<bool UseMemorySSA>
18680b57cec5SDimitry Andric class EarlyCSELegacyCommonPass : public FunctionPass {
18690b57cec5SDimitry Andric public:
18700b57cec5SDimitry Andric   static char ID;
18710b57cec5SDimitry Andric 
18720b57cec5SDimitry Andric   EarlyCSELegacyCommonPass() : FunctionPass(ID) {
18730b57cec5SDimitry Andric     if (UseMemorySSA)
18740b57cec5SDimitry Andric       initializeEarlyCSEMemSSALegacyPassPass(*PassRegistry::getPassRegistry());
18750b57cec5SDimitry Andric     else
18760b57cec5SDimitry Andric       initializeEarlyCSELegacyPassPass(*PassRegistry::getPassRegistry());
18770b57cec5SDimitry Andric   }
18780b57cec5SDimitry Andric 
18790b57cec5SDimitry Andric   bool runOnFunction(Function &F) override {
18800b57cec5SDimitry Andric     if (skipFunction(F))
18810b57cec5SDimitry Andric       return false;
18820b57cec5SDimitry Andric 
18838bcb0991SDimitry Andric     auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
18840b57cec5SDimitry Andric     auto &TTI = getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
18850b57cec5SDimitry Andric     auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
18860b57cec5SDimitry Andric     auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
18870b57cec5SDimitry Andric     auto *MSSA =
18880b57cec5SDimitry Andric         UseMemorySSA ? &getAnalysis<MemorySSAWrapperPass>().getMSSA() : nullptr;
18890b57cec5SDimitry Andric 
1890*0fca6ea1SDimitry Andric     EarlyCSE CSE(F.getDataLayout(), TLI, TTI, DT, AC, MSSA);
18910b57cec5SDimitry Andric 
18920b57cec5SDimitry Andric     return CSE.run();
18930b57cec5SDimitry Andric   }
18940b57cec5SDimitry Andric 
18950b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
18960b57cec5SDimitry Andric     AU.addRequired<AssumptionCacheTracker>();
18970b57cec5SDimitry Andric     AU.addRequired<DominatorTreeWrapperPass>();
18980b57cec5SDimitry Andric     AU.addRequired<TargetLibraryInfoWrapperPass>();
18990b57cec5SDimitry Andric     AU.addRequired<TargetTransformInfoWrapperPass>();
19000b57cec5SDimitry Andric     if (UseMemorySSA) {
1901e8d8bef9SDimitry Andric       AU.addRequired<AAResultsWrapperPass>();
19020b57cec5SDimitry Andric       AU.addRequired<MemorySSAWrapperPass>();
19030b57cec5SDimitry Andric       AU.addPreserved<MemorySSAWrapperPass>();
19040b57cec5SDimitry Andric     }
19050b57cec5SDimitry Andric     AU.addPreserved<GlobalsAAWrapperPass>();
19068bcb0991SDimitry Andric     AU.addPreserved<AAResultsWrapperPass>();
19070b57cec5SDimitry Andric     AU.setPreservesCFG();
19080b57cec5SDimitry Andric   }
19090b57cec5SDimitry Andric };
19100b57cec5SDimitry Andric 
19110b57cec5SDimitry Andric } // end anonymous namespace
19120b57cec5SDimitry Andric 
19130b57cec5SDimitry Andric using EarlyCSELegacyPass = EarlyCSELegacyCommonPass</*UseMemorySSA=*/false>;
19140b57cec5SDimitry Andric 
19150b57cec5SDimitry Andric template<>
19160b57cec5SDimitry Andric char EarlyCSELegacyPass::ID = 0;
19170b57cec5SDimitry Andric 
19180b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(EarlyCSELegacyPass, "early-cse", "Early CSE", false,
19190b57cec5SDimitry Andric                       false)
19200b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
19210b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
19220b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
19230b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
19240b57cec5SDimitry Andric INITIALIZE_PASS_END(EarlyCSELegacyPass, "early-cse", "Early CSE", false, false)
19250b57cec5SDimitry Andric 
19260b57cec5SDimitry Andric using EarlyCSEMemSSALegacyPass =
19270b57cec5SDimitry Andric     EarlyCSELegacyCommonPass</*UseMemorySSA=*/true>;
19280b57cec5SDimitry Andric 
19290b57cec5SDimitry Andric template<>
19300b57cec5SDimitry Andric char EarlyCSEMemSSALegacyPass::ID = 0;
19310b57cec5SDimitry Andric 
19320b57cec5SDimitry Andric FunctionPass *llvm::createEarlyCSEPass(bool UseMemorySSA) {
19330b57cec5SDimitry Andric   if (UseMemorySSA)
19340b57cec5SDimitry Andric     return new EarlyCSEMemSSALegacyPass();
19350b57cec5SDimitry Andric   else
19360b57cec5SDimitry Andric     return new EarlyCSELegacyPass();
19370b57cec5SDimitry Andric }
19380b57cec5SDimitry Andric 
19390b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(EarlyCSEMemSSALegacyPass, "early-cse-memssa",
19400b57cec5SDimitry Andric                       "Early CSE w/ MemorySSA", false, false)
19410b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
19420b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
1943e8d8bef9SDimitry Andric INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
19440b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
19450b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
19460b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MemorySSAWrapperPass)
19470b57cec5SDimitry Andric INITIALIZE_PASS_END(EarlyCSEMemSSALegacyPass, "early-cse-memssa",
19480b57cec5SDimitry Andric                     "Early CSE w/ MemorySSA", false, false)
1949