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