xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/IPO/GlobalOpt.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- GlobalOpt.cpp - Optimize Global Variables --------------------------===//
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 transforms simple global variables that never have their address
100b57cec5SDimitry Andric // taken.  If obviously true, it marks read/write globals as constant, deletes
110b57cec5SDimitry Andric // variables only stored to, etc.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "llvm/Transforms/IPO/GlobalOpt.h"
160b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
170b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
180b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
190b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
200b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
210b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
220b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h"
230b57cec5SDimitry Andric #include "llvm/Analysis/BlockFrequencyInfo.h"
240b57cec5SDimitry Andric #include "llvm/Analysis/ConstantFolding.h"
250b57cec5SDimitry Andric #include "llvm/Analysis/MemoryBuiltins.h"
260b57cec5SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h"
270b57cec5SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h"
284824e7fdSDimitry Andric #include "llvm/Analysis/ValueTracking.h"
290b57cec5SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h"
300b57cec5SDimitry Andric #include "llvm/IR/Attributes.h"
310b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h"
320b57cec5SDimitry Andric #include "llvm/IR/CallingConv.h"
330b57cec5SDimitry Andric #include "llvm/IR/Constant.h"
340b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
350b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
360b57cec5SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
370b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h"
380b57cec5SDimitry Andric #include "llvm/IR/Dominators.h"
390b57cec5SDimitry Andric #include "llvm/IR/Function.h"
400b57cec5SDimitry Andric #include "llvm/IR/GlobalAlias.h"
410b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
420b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h"
435ffd83dbSDimitry Andric #include "llvm/IR/IRBuilder.h"
440b57cec5SDimitry Andric #include "llvm/IR/InstrTypes.h"
450b57cec5SDimitry Andric #include "llvm/IR/Instruction.h"
460b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
470b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
480b57cec5SDimitry Andric #include "llvm/IR/Module.h"
490b57cec5SDimitry Andric #include "llvm/IR/Operator.h"
500b57cec5SDimitry Andric #include "llvm/IR/Type.h"
510b57cec5SDimitry Andric #include "llvm/IR/Use.h"
520b57cec5SDimitry Andric #include "llvm/IR/User.h"
530b57cec5SDimitry Andric #include "llvm/IR/Value.h"
540b57cec5SDimitry Andric #include "llvm/IR/ValueHandle.h"
550b57cec5SDimitry Andric #include "llvm/Support/AtomicOrdering.h"
560b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
570b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
580b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
590b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
600b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
610b57cec5SDimitry Andric #include "llvm/Transforms/IPO.h"
620b57cec5SDimitry Andric #include "llvm/Transforms/Utils/CtorUtils.h"
630b57cec5SDimitry Andric #include "llvm/Transforms/Utils/Evaluator.h"
640b57cec5SDimitry Andric #include "llvm/Transforms/Utils/GlobalStatus.h"
65480093f4SDimitry Andric #include "llvm/Transforms/Utils/Local.h"
660b57cec5SDimitry Andric #include <cassert>
670b57cec5SDimitry Andric #include <cstdint>
68bdd1243dSDimitry Andric #include <optional>
690b57cec5SDimitry Andric #include <utility>
700b57cec5SDimitry Andric #include <vector>
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric using namespace llvm;
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric #define DEBUG_TYPE "globalopt"
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric STATISTIC(NumMarked    , "Number of globals marked constant");
770b57cec5SDimitry Andric STATISTIC(NumUnnamed   , "Number of globals marked unnamed_addr");
780b57cec5SDimitry Andric STATISTIC(NumSRA       , "Number of aggregate globals broken into scalars");
790b57cec5SDimitry Andric STATISTIC(NumSubstitute,"Number of globals with initializers stored into them");
800b57cec5SDimitry Andric STATISTIC(NumDeleted   , "Number of globals deleted");
810b57cec5SDimitry Andric STATISTIC(NumGlobUses  , "Number of global uses devirtualized");
820b57cec5SDimitry Andric STATISTIC(NumLocalized , "Number of globals localized");
830b57cec5SDimitry Andric STATISTIC(NumShrunkToBool  , "Number of global vars shrunk to booleans");
840b57cec5SDimitry Andric STATISTIC(NumFastCallFns   , "Number of functions converted to fastcc");
850b57cec5SDimitry Andric STATISTIC(NumCtorsEvaluated, "Number of static ctors evaluated");
860b57cec5SDimitry Andric STATISTIC(NumNestRemoved   , "Number of nest attributes removed");
870b57cec5SDimitry Andric STATISTIC(NumAliasesResolved, "Number of global aliases resolved");
880b57cec5SDimitry Andric STATISTIC(NumAliasesRemoved, "Number of global aliases eliminated");
890b57cec5SDimitry Andric STATISTIC(NumCXXDtorsRemoved, "Number of global C++ destructors removed");
90*0fca6ea1SDimitry Andric STATISTIC(NumAtExitRemoved, "Number of atexit handlers removed");
910b57cec5SDimitry Andric STATISTIC(NumInternalFunc, "Number of internal functions");
920b57cec5SDimitry Andric STATISTIC(NumColdCC, "Number of functions marked coldcc");
93*0fca6ea1SDimitry Andric STATISTIC(NumIFuncsResolved, "Number of statically resolved IFuncs");
94*0fca6ea1SDimitry Andric STATISTIC(NumIFuncsDeleted, "Number of IFuncs removed");
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric static cl::opt<bool>
970b57cec5SDimitry Andric     EnableColdCCStressTest("enable-coldcc-stress-test",
980b57cec5SDimitry Andric                            cl::desc("Enable stress test of coldcc by adding "
990b57cec5SDimitry Andric                                     "calling conv to all internal functions."),
1000b57cec5SDimitry Andric                            cl::init(false), cl::Hidden);
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric static cl::opt<int> ColdCCRelFreq(
10381ad6265SDimitry Andric     "coldcc-rel-freq", cl::Hidden, cl::init(2),
1040b57cec5SDimitry Andric     cl::desc(
1050b57cec5SDimitry Andric         "Maximum block frequency, expressed as a percentage of caller's "
1060b57cec5SDimitry Andric         "entry frequency, for a call site to be considered cold for enabling"
1070b57cec5SDimitry Andric         "coldcc"));
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric /// Is this global variable possibly used by a leak checker as a root?  If so,
1100b57cec5SDimitry Andric /// we might not really want to eliminate the stores to it.
1110b57cec5SDimitry Andric static bool isLeakCheckerRoot(GlobalVariable *GV) {
1120b57cec5SDimitry Andric   // A global variable is a root if it is a pointer, or could plausibly contain
1130b57cec5SDimitry Andric   // a pointer.  There are two challenges; one is that we could have a struct
1140b57cec5SDimitry Andric   // the has an inner member which is a pointer.  We recurse through the type to
1150b57cec5SDimitry Andric   // detect these (up to a point).  The other is that we may actually be a union
1160b57cec5SDimitry Andric   // of a pointer and another type, and so our LLVM type is an integer which
1170b57cec5SDimitry Andric   // gets converted into a pointer, or our type is an [i8 x #] with a pointer
1180b57cec5SDimitry Andric   // potentially contained here.
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   if (GV->hasPrivateLinkage())
1210b57cec5SDimitry Andric     return false;
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric   SmallVector<Type *, 4> Types;
1240b57cec5SDimitry Andric   Types.push_back(GV->getValueType());
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   unsigned Limit = 20;
1270b57cec5SDimitry Andric   do {
1280b57cec5SDimitry Andric     Type *Ty = Types.pop_back_val();
1290b57cec5SDimitry Andric     switch (Ty->getTypeID()) {
1300b57cec5SDimitry Andric       default: break;
1315ffd83dbSDimitry Andric       case Type::PointerTyID:
1325ffd83dbSDimitry Andric         return true;
1335ffd83dbSDimitry Andric       case Type::FixedVectorTyID:
1345ffd83dbSDimitry Andric       case Type::ScalableVectorTyID:
1355ffd83dbSDimitry Andric         if (cast<VectorType>(Ty)->getElementType()->isPointerTy())
1365ffd83dbSDimitry Andric           return true;
1370b57cec5SDimitry Andric         break;
1385ffd83dbSDimitry Andric       case Type::ArrayTyID:
1395ffd83dbSDimitry Andric         Types.push_back(cast<ArrayType>(Ty)->getElementType());
1405ffd83dbSDimitry Andric         break;
1410b57cec5SDimitry Andric       case Type::StructTyID: {
1420b57cec5SDimitry Andric         StructType *STy = cast<StructType>(Ty);
1430b57cec5SDimitry Andric         if (STy->isOpaque()) return true;
144bdd1243dSDimitry Andric         for (Type *InnerTy : STy->elements()) {
1450b57cec5SDimitry Andric           if (isa<PointerType>(InnerTy)) return true;
1465ffd83dbSDimitry Andric           if (isa<StructType>(InnerTy) || isa<ArrayType>(InnerTy) ||
1475ffd83dbSDimitry Andric               isa<VectorType>(InnerTy))
1480b57cec5SDimitry Andric             Types.push_back(InnerTy);
1490b57cec5SDimitry Andric         }
1500b57cec5SDimitry Andric         break;
1510b57cec5SDimitry Andric       }
1520b57cec5SDimitry Andric     }
1530b57cec5SDimitry Andric     if (--Limit == 0) return true;
1540b57cec5SDimitry Andric   } while (!Types.empty());
1550b57cec5SDimitry Andric   return false;
1560b57cec5SDimitry Andric }
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric /// Given a value that is stored to a global but never read, determine whether
1590b57cec5SDimitry Andric /// it's safe to remove the store and the chain of computation that feeds the
1600b57cec5SDimitry Andric /// store.
1618bcb0991SDimitry Andric static bool IsSafeComputationToRemove(
1628bcb0991SDimitry Andric     Value *V, function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
1630b57cec5SDimitry Andric   do {
1640b57cec5SDimitry Andric     if (isa<Constant>(V))
1650b57cec5SDimitry Andric       return true;
1660b57cec5SDimitry Andric     if (!V->hasOneUse())
1670b57cec5SDimitry Andric       return false;
1680b57cec5SDimitry Andric     if (isa<LoadInst>(V) || isa<InvokeInst>(V) || isa<Argument>(V) ||
1690b57cec5SDimitry Andric         isa<GlobalValue>(V))
1700b57cec5SDimitry Andric       return false;
1718bcb0991SDimitry Andric     if (isAllocationFn(V, GetTLI))
1720b57cec5SDimitry Andric       return true;
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric     Instruction *I = cast<Instruction>(V);
1750b57cec5SDimitry Andric     if (I->mayHaveSideEffects())
1760b57cec5SDimitry Andric       return false;
1770b57cec5SDimitry Andric     if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(I)) {
1780b57cec5SDimitry Andric       if (!GEP->hasAllConstantIndices())
1790b57cec5SDimitry Andric         return false;
1800b57cec5SDimitry Andric     } else if (I->getNumOperands() != 1) {
1810b57cec5SDimitry Andric       return false;
1820b57cec5SDimitry Andric     }
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric     V = I->getOperand(0);
1850b57cec5SDimitry Andric   } while (true);
1860b57cec5SDimitry Andric }
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric /// This GV is a pointer root.  Loop over all users of the global and clean up
1890b57cec5SDimitry Andric /// any that obviously don't assign the global a value that isn't dynamically
1900b57cec5SDimitry Andric /// allocated.
1918bcb0991SDimitry Andric static bool
1928bcb0991SDimitry Andric CleanupPointerRootUsers(GlobalVariable *GV,
1938bcb0991SDimitry Andric                         function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
1940b57cec5SDimitry Andric   // A brief explanation of leak checkers.  The goal is to find bugs where
1950b57cec5SDimitry Andric   // pointers are forgotten, causing an accumulating growth in memory
1965ffd83dbSDimitry Andric   // usage over time.  The common strategy for leak checkers is to explicitly
1975ffd83dbSDimitry Andric   // allow the memory pointed to by globals at exit.  This is popular because it
1985ffd83dbSDimitry Andric   // also solves another problem where the main thread of a C++ program may shut
1995ffd83dbSDimitry Andric   // down before other threads that are still expecting to use those globals. To
2000b57cec5SDimitry Andric   // handle that case, we expect the program may create a singleton and never
2010b57cec5SDimitry Andric   // destroy it.
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric   bool Changed = false;
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric   // If Dead[n].first is the only use of a malloc result, we can delete its
2060b57cec5SDimitry Andric   // chain of computation and the store to the global in Dead[n].second.
2070b57cec5SDimitry Andric   SmallVector<std::pair<Instruction *, Instruction *>, 32> Dead;
2080b57cec5SDimitry Andric 
20906c3fb27SDimitry Andric   SmallVector<User *> Worklist(GV->users());
2100b57cec5SDimitry Andric   // Constants can't be pointers to dynamically allocated memory.
21106c3fb27SDimitry Andric   while (!Worklist.empty()) {
21206c3fb27SDimitry Andric     User *U = Worklist.pop_back_val();
2130b57cec5SDimitry Andric     if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
2140b57cec5SDimitry Andric       Value *V = SI->getValueOperand();
2150b57cec5SDimitry Andric       if (isa<Constant>(V)) {
2160b57cec5SDimitry Andric         Changed = true;
2170b57cec5SDimitry Andric         SI->eraseFromParent();
2180b57cec5SDimitry Andric       } else if (Instruction *I = dyn_cast<Instruction>(V)) {
2190b57cec5SDimitry Andric         if (I->hasOneUse())
2200b57cec5SDimitry Andric           Dead.push_back(std::make_pair(I, SI));
2210b57cec5SDimitry Andric       }
2220b57cec5SDimitry Andric     } else if (MemSetInst *MSI = dyn_cast<MemSetInst>(U)) {
2230b57cec5SDimitry Andric       if (isa<Constant>(MSI->getValue())) {
2240b57cec5SDimitry Andric         Changed = true;
2250b57cec5SDimitry Andric         MSI->eraseFromParent();
2260b57cec5SDimitry Andric       } else if (Instruction *I = dyn_cast<Instruction>(MSI->getValue())) {
2270b57cec5SDimitry Andric         if (I->hasOneUse())
2280b57cec5SDimitry Andric           Dead.push_back(std::make_pair(I, MSI));
2290b57cec5SDimitry Andric       }
2300b57cec5SDimitry Andric     } else if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(U)) {
2310b57cec5SDimitry Andric       GlobalVariable *MemSrc = dyn_cast<GlobalVariable>(MTI->getSource());
2320b57cec5SDimitry Andric       if (MemSrc && MemSrc->isConstant()) {
2330b57cec5SDimitry Andric         Changed = true;
2340b57cec5SDimitry Andric         MTI->eraseFromParent();
23581ad6265SDimitry Andric       } else if (Instruction *I = dyn_cast<Instruction>(MTI->getSource())) {
2360b57cec5SDimitry Andric         if (I->hasOneUse())
2370b57cec5SDimitry Andric           Dead.push_back(std::make_pair(I, MTI));
2380b57cec5SDimitry Andric       }
2390b57cec5SDimitry Andric     } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U)) {
24006c3fb27SDimitry Andric       if (isa<GEPOperator>(CE))
24106c3fb27SDimitry Andric         append_range(Worklist, CE->users());
2420b57cec5SDimitry Andric     }
2430b57cec5SDimitry Andric   }
2440b57cec5SDimitry Andric 
2450b57cec5SDimitry Andric   for (int i = 0, e = Dead.size(); i != e; ++i) {
2468bcb0991SDimitry Andric     if (IsSafeComputationToRemove(Dead[i].first, GetTLI)) {
2470b57cec5SDimitry Andric       Dead[i].second->eraseFromParent();
2480b57cec5SDimitry Andric       Instruction *I = Dead[i].first;
2490b57cec5SDimitry Andric       do {
2508bcb0991SDimitry Andric         if (isAllocationFn(I, GetTLI))
2510b57cec5SDimitry Andric           break;
2520b57cec5SDimitry Andric         Instruction *J = dyn_cast<Instruction>(I->getOperand(0));
2530b57cec5SDimitry Andric         if (!J)
2540b57cec5SDimitry Andric           break;
2550b57cec5SDimitry Andric         I->eraseFromParent();
2560b57cec5SDimitry Andric         I = J;
2570b57cec5SDimitry Andric       } while (true);
2580b57cec5SDimitry Andric       I->eraseFromParent();
259e8d8bef9SDimitry Andric       Changed = true;
2600b57cec5SDimitry Andric     }
2610b57cec5SDimitry Andric   }
2620b57cec5SDimitry Andric 
26306c3fb27SDimitry Andric   GV->removeDeadConstantUsers();
2640b57cec5SDimitry Andric   return Changed;
2650b57cec5SDimitry Andric }
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric /// We just marked GV constant.  Loop over all users of the global, cleaning up
2680b57cec5SDimitry Andric /// the obvious ones.  This is largely just a quick scan over the use list to
2690b57cec5SDimitry Andric /// clean up the easy and obvious cruft.  This returns true if it made a change.
2704824e7fdSDimitry Andric static bool CleanupConstantGlobalUsers(GlobalVariable *GV,
2714824e7fdSDimitry Andric                                        const DataLayout &DL) {
2724824e7fdSDimitry Andric   Constant *Init = GV->getInitializer();
2734824e7fdSDimitry Andric   SmallVector<User *, 8> WorkList(GV->users());
2744824e7fdSDimitry Andric   SmallPtrSet<User *, 8> Visited;
2750b57cec5SDimitry Andric   bool Changed = false;
2764824e7fdSDimitry Andric 
2774824e7fdSDimitry Andric   SmallVector<WeakTrackingVH> MaybeDeadInsts;
2784824e7fdSDimitry Andric   auto EraseFromParent = [&](Instruction *I) {
2794824e7fdSDimitry Andric     for (Value *Op : I->operands())
2804824e7fdSDimitry Andric       if (auto *OpI = dyn_cast<Instruction>(Op))
2814824e7fdSDimitry Andric         MaybeDeadInsts.push_back(OpI);
2824824e7fdSDimitry Andric     I->eraseFromParent();
2834824e7fdSDimitry Andric     Changed = true;
2844824e7fdSDimitry Andric   };
2850b57cec5SDimitry Andric   while (!WorkList.empty()) {
2864824e7fdSDimitry Andric     User *U = WorkList.pop_back_val();
2874824e7fdSDimitry Andric     if (!Visited.insert(U).second)
2880b57cec5SDimitry Andric       continue;
2890b57cec5SDimitry Andric 
2904824e7fdSDimitry Andric     if (auto *BO = dyn_cast<BitCastOperator>(U))
2914824e7fdSDimitry Andric       append_range(WorkList, BO->users());
2924824e7fdSDimitry Andric     if (auto *ASC = dyn_cast<AddrSpaceCastOperator>(U))
2934824e7fdSDimitry Andric       append_range(WorkList, ASC->users());
2944824e7fdSDimitry Andric     else if (auto *GEP = dyn_cast<GEPOperator>(U))
2954824e7fdSDimitry Andric       append_range(WorkList, GEP->users());
2964824e7fdSDimitry Andric     else if (auto *LI = dyn_cast<LoadInst>(U)) {
29704eeddc0SDimitry Andric       // A load from a uniform value is always the same, regardless of any
29804eeddc0SDimitry Andric       // applied offset.
2990eae32dcSDimitry Andric       Type *Ty = LI->getType();
300*0fca6ea1SDimitry Andric       if (Constant *Res = ConstantFoldLoadFromUniformValue(Init, Ty, DL)) {
30104eeddc0SDimitry Andric         LI->replaceAllUsesWith(Res);
3024824e7fdSDimitry Andric         EraseFromParent(LI);
3034824e7fdSDimitry Andric         continue;
3044824e7fdSDimitry Andric       }
3050b57cec5SDimitry Andric 
3064824e7fdSDimitry Andric       Value *PtrOp = LI->getPointerOperand();
3074824e7fdSDimitry Andric       APInt Offset(DL.getIndexTypeSizeInBits(PtrOp->getType()), 0);
3084824e7fdSDimitry Andric       PtrOp = PtrOp->stripAndAccumulateConstantOffsets(
3094824e7fdSDimitry Andric           DL, Offset, /* AllowNonInbounds */ true);
310*0fca6ea1SDimitry Andric       if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(PtrOp)) {
311*0fca6ea1SDimitry Andric         if (II->getIntrinsicID() == Intrinsic::threadlocal_address)
312*0fca6ea1SDimitry Andric           PtrOp = II->getArgOperand(0);
313*0fca6ea1SDimitry Andric       }
3144824e7fdSDimitry Andric       if (PtrOp == GV) {
3150eae32dcSDimitry Andric         if (auto *Value = ConstantFoldLoadFromConst(Init, Ty, Offset, DL)) {
3164824e7fdSDimitry Andric           LI->replaceAllUsesWith(Value);
3174824e7fdSDimitry Andric           EraseFromParent(LI);
3180b57cec5SDimitry Andric         }
319fe6060f1SDimitry Andric       }
3200b57cec5SDimitry Andric     } else if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
3210b57cec5SDimitry Andric       // Store must be unreachable or storing Init into the global.
3224824e7fdSDimitry Andric       EraseFromParent(SI);
3230b57cec5SDimitry Andric     } else if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(U)) { // memset/cpy/mv
3244824e7fdSDimitry Andric       if (getUnderlyingObject(MI->getRawDest()) == GV)
3254824e7fdSDimitry Andric         EraseFromParent(MI);
326*0fca6ea1SDimitry Andric     } else if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(U)) {
327*0fca6ea1SDimitry Andric       if (II->getIntrinsicID() == Intrinsic::threadlocal_address)
328*0fca6ea1SDimitry Andric         append_range(WorkList, II->users());
3294824e7fdSDimitry Andric     }
3300b57cec5SDimitry Andric   }
3310b57cec5SDimitry Andric 
3324824e7fdSDimitry Andric   Changed |=
3334824e7fdSDimitry Andric       RecursivelyDeleteTriviallyDeadInstructionsPermissive(MaybeDeadInsts);
3344824e7fdSDimitry Andric   GV->removeDeadConstantUsers();
3350b57cec5SDimitry Andric   return Changed;
3360b57cec5SDimitry Andric }
3370b57cec5SDimitry Andric 
33806c3fb27SDimitry Andric /// Part of the global at a specific offset, which is only accessed through
33906c3fb27SDimitry Andric /// loads and stores with the given type.
34006c3fb27SDimitry Andric struct GlobalPart {
34106c3fb27SDimitry Andric   Type *Ty;
34206c3fb27SDimitry Andric   Constant *Initializer = nullptr;
34306c3fb27SDimitry Andric   bool IsLoaded = false;
34406c3fb27SDimitry Andric   bool IsStored = false;
34506c3fb27SDimitry Andric };
34606c3fb27SDimitry Andric 
34704eeddc0SDimitry Andric /// Look at all uses of the global and determine which (offset, type) pairs it
34804eeddc0SDimitry Andric /// can be split into.
34906c3fb27SDimitry Andric static bool collectSRATypes(DenseMap<uint64_t, GlobalPart> &Parts,
35006c3fb27SDimitry Andric                             GlobalVariable *GV, const DataLayout &DL) {
35104eeddc0SDimitry Andric   SmallVector<Use *, 16> Worklist;
35204eeddc0SDimitry Andric   SmallPtrSet<Use *, 16> Visited;
35304eeddc0SDimitry Andric   auto AppendUses = [&](Value *V) {
35404eeddc0SDimitry Andric     for (Use &U : V->uses())
35504eeddc0SDimitry Andric       if (Visited.insert(&U).second)
35604eeddc0SDimitry Andric         Worklist.push_back(&U);
35704eeddc0SDimitry Andric   };
35804eeddc0SDimitry Andric   AppendUses(GV);
35904eeddc0SDimitry Andric   while (!Worklist.empty()) {
36004eeddc0SDimitry Andric     Use *U = Worklist.pop_back_val();
36104eeddc0SDimitry Andric     User *V = U->getUser();
3620b57cec5SDimitry Andric 
3631fd87a68SDimitry Andric     auto *GEP = dyn_cast<GEPOperator>(V);
3641fd87a68SDimitry Andric     if (isa<BitCastOperator>(V) || isa<AddrSpaceCastOperator>(V) ||
3651fd87a68SDimitry Andric         (GEP && GEP->hasAllConstantIndices())) {
36604eeddc0SDimitry Andric       AppendUses(V);
36704eeddc0SDimitry Andric       continue;
3680b57cec5SDimitry Andric     }
3690b57cec5SDimitry Andric 
37004eeddc0SDimitry Andric     if (Value *Ptr = getLoadStorePointerOperand(V)) {
37104eeddc0SDimitry Andric       // This is storing the global address into somewhere, not storing into
37204eeddc0SDimitry Andric       // the global.
37304eeddc0SDimitry Andric       if (isa<StoreInst>(V) && U->getOperandNo() == 0)
3740b57cec5SDimitry Andric         return false;
3750b57cec5SDimitry Andric 
37604eeddc0SDimitry Andric       APInt Offset(DL.getIndexTypeSizeInBits(Ptr->getType()), 0);
37704eeddc0SDimitry Andric       Ptr = Ptr->stripAndAccumulateConstantOffsets(DL, Offset,
37804eeddc0SDimitry Andric                                                    /* AllowNonInbounds */ true);
37904eeddc0SDimitry Andric       if (Ptr != GV || Offset.getActiveBits() >= 64)
38004eeddc0SDimitry Andric         return false;
38104eeddc0SDimitry Andric 
38204eeddc0SDimitry Andric       // TODO: We currently require that all accesses at a given offset must
38304eeddc0SDimitry Andric       // use the same type. This could be relaxed.
38404eeddc0SDimitry Andric       Type *Ty = getLoadStoreType(V);
38506c3fb27SDimitry Andric       const auto &[It, Inserted] =
38606c3fb27SDimitry Andric           Parts.try_emplace(Offset.getZExtValue(), GlobalPart{Ty});
38706c3fb27SDimitry Andric       if (Ty != It->second.Ty)
38804eeddc0SDimitry Andric         return false;
389bdd1243dSDimitry Andric 
39006c3fb27SDimitry Andric       if (Inserted) {
39106c3fb27SDimitry Andric         It->second.Initializer =
39206c3fb27SDimitry Andric             ConstantFoldLoadFromConst(GV->getInitializer(), Ty, Offset, DL);
39306c3fb27SDimitry Andric         if (!It->second.Initializer) {
39406c3fb27SDimitry Andric           LLVM_DEBUG(dbgs() << "Global SRA: Failed to evaluate initializer of "
39506c3fb27SDimitry Andric                             << *GV << " with type " << *Ty << " at offset "
39606c3fb27SDimitry Andric                             << Offset.getZExtValue());
39706c3fb27SDimitry Andric           return false;
39806c3fb27SDimitry Andric         }
39906c3fb27SDimitry Andric       }
40006c3fb27SDimitry Andric 
401bdd1243dSDimitry Andric       // Scalable types not currently supported.
4025f757f3fSDimitry Andric       if (Ty->isScalableTy())
403bdd1243dSDimitry Andric         return false;
404bdd1243dSDimitry Andric 
40506c3fb27SDimitry Andric       auto IsStored = [](Value *V, Constant *Initializer) {
40606c3fb27SDimitry Andric         auto *SI = dyn_cast<StoreInst>(V);
40706c3fb27SDimitry Andric         if (!SI)
40806c3fb27SDimitry Andric           return false;
40906c3fb27SDimitry Andric 
41006c3fb27SDimitry Andric         Constant *StoredConst = dyn_cast<Constant>(SI->getOperand(0));
41106c3fb27SDimitry Andric         if (!StoredConst)
41206c3fb27SDimitry Andric           return true;
41306c3fb27SDimitry Andric 
41406c3fb27SDimitry Andric         // Don't consider stores that only write the initializer value.
41506c3fb27SDimitry Andric         return Initializer != StoredConst;
41606c3fb27SDimitry Andric       };
41706c3fb27SDimitry Andric 
41806c3fb27SDimitry Andric       It->second.IsLoaded |= isa<LoadInst>(V);
41906c3fb27SDimitry Andric       It->second.IsStored |= IsStored(V, It->second.Initializer);
42004eeddc0SDimitry Andric       continue;
42104eeddc0SDimitry Andric     }
42204eeddc0SDimitry Andric 
42304eeddc0SDimitry Andric     // Ignore dead constant users.
42404eeddc0SDimitry Andric     if (auto *C = dyn_cast<Constant>(V)) {
42504eeddc0SDimitry Andric       if (!isSafeToDestroyConstant(C))
42604eeddc0SDimitry Andric         return false;
42704eeddc0SDimitry Andric       continue;
42804eeddc0SDimitry Andric     }
42904eeddc0SDimitry Andric 
43004eeddc0SDimitry Andric     // Unknown user.
4310b57cec5SDimitry Andric     return false;
4320b57cec5SDimitry Andric   }
4330b57cec5SDimitry Andric 
4340b57cec5SDimitry Andric   return true;
4350b57cec5SDimitry Andric }
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric /// Copy over the debug info for a variable to its SRA replacements.
4380b57cec5SDimitry Andric static void transferSRADebugInfo(GlobalVariable *GV, GlobalVariable *NGV,
4390b57cec5SDimitry Andric                                  uint64_t FragmentOffsetInBits,
44075b4d546SDimitry Andric                                  uint64_t FragmentSizeInBits,
44175b4d546SDimitry Andric                                  uint64_t VarSize) {
4420b57cec5SDimitry Andric   SmallVector<DIGlobalVariableExpression *, 1> GVs;
4430b57cec5SDimitry Andric   GV->getDebugInfo(GVs);
4440b57cec5SDimitry Andric   for (auto *GVE : GVs) {
4450b57cec5SDimitry Andric     DIVariable *Var = GVE->getVariable();
4460b57cec5SDimitry Andric     DIExpression *Expr = GVE->getExpression();
44781ad6265SDimitry Andric     int64_t CurVarOffsetInBytes = 0;
44881ad6265SDimitry Andric     uint64_t CurVarOffsetInBits = 0;
44906c3fb27SDimitry Andric     uint64_t FragmentEndInBits = FragmentOffsetInBits + FragmentSizeInBits;
45081ad6265SDimitry Andric 
45181ad6265SDimitry Andric     // Calculate the offset (Bytes), Continue if unknown.
45281ad6265SDimitry Andric     if (!Expr->extractIfOffset(CurVarOffsetInBytes))
45381ad6265SDimitry Andric       continue;
45481ad6265SDimitry Andric 
45581ad6265SDimitry Andric     // Ignore negative offset.
45681ad6265SDimitry Andric     if (CurVarOffsetInBytes < 0)
45781ad6265SDimitry Andric       continue;
45881ad6265SDimitry Andric 
45981ad6265SDimitry Andric     // Convert offset to bits.
46081ad6265SDimitry Andric     CurVarOffsetInBits = CHAR_BIT * (uint64_t)CurVarOffsetInBytes;
46181ad6265SDimitry Andric 
46281ad6265SDimitry Andric     // Current var starts after the fragment, ignore.
46306c3fb27SDimitry Andric     if (CurVarOffsetInBits >= FragmentEndInBits)
46481ad6265SDimitry Andric       continue;
46581ad6265SDimitry Andric 
46681ad6265SDimitry Andric     uint64_t CurVarSize = Var->getType()->getSizeInBits();
46706c3fb27SDimitry Andric     uint64_t CurVarEndInBits = CurVarOffsetInBits + CurVarSize;
46881ad6265SDimitry Andric     // Current variable ends before start of fragment, ignore.
46906c3fb27SDimitry Andric     if (CurVarSize != 0 && /* CurVarSize is known */
47006c3fb27SDimitry Andric         CurVarEndInBits <= FragmentOffsetInBits)
47181ad6265SDimitry Andric       continue;
47281ad6265SDimitry Andric 
47306c3fb27SDimitry Andric     // Current variable fits in (not greater than) the fragment,
47406c3fb27SDimitry Andric     // does not need fragment expression.
47506c3fb27SDimitry Andric     if (CurVarSize != 0 && /* CurVarSize is known */
47606c3fb27SDimitry Andric         CurVarOffsetInBits >= FragmentOffsetInBits &&
47706c3fb27SDimitry Andric         CurVarEndInBits <= FragmentEndInBits) {
47806c3fb27SDimitry Andric       uint64_t CurVarOffsetInFragment =
47906c3fb27SDimitry Andric           (CurVarOffsetInBits - FragmentOffsetInBits) / 8;
48006c3fb27SDimitry Andric       if (CurVarOffsetInFragment != 0)
48106c3fb27SDimitry Andric         Expr = DIExpression::get(Expr->getContext(), {dwarf::DW_OP_plus_uconst,
48206c3fb27SDimitry Andric                                                       CurVarOffsetInFragment});
48306c3fb27SDimitry Andric       else
48481ad6265SDimitry Andric         Expr = DIExpression::get(Expr->getContext(), {});
48506c3fb27SDimitry Andric       auto *NGVE =
48606c3fb27SDimitry Andric           DIGlobalVariableExpression::get(GVE->getContext(), Var, Expr);
48706c3fb27SDimitry Andric       NGV->addDebugInfo(NGVE);
48806c3fb27SDimitry Andric       continue;
48906c3fb27SDimitry Andric     }
49006c3fb27SDimitry Andric     // Current variable does not fit in single fragment,
491d65cd7a5SDimitry Andric     // emit a fragment expression.
49206c3fb27SDimitry Andric     if (FragmentSizeInBits < VarSize) {
49306c3fb27SDimitry Andric       if (CurVarOffsetInBits > FragmentOffsetInBits)
49406c3fb27SDimitry Andric         continue;
49506c3fb27SDimitry Andric       uint64_t CurVarFragmentOffsetInBits =
49606c3fb27SDimitry Andric           FragmentOffsetInBits - CurVarOffsetInBits;
49706c3fb27SDimitry Andric       uint64_t CurVarFragmentSizeInBits = FragmentSizeInBits;
49806c3fb27SDimitry Andric       if (CurVarSize != 0 && CurVarEndInBits < FragmentEndInBits)
49906c3fb27SDimitry Andric         CurVarFragmentSizeInBits -= (FragmentEndInBits - CurVarEndInBits);
50006c3fb27SDimitry Andric       if (CurVarOffsetInBits)
50106c3fb27SDimitry Andric         Expr = DIExpression::get(Expr->getContext(), {});
5020b57cec5SDimitry Andric       if (auto E = DIExpression::createFragmentExpression(
50306c3fb27SDimitry Andric               Expr, CurVarFragmentOffsetInBits, CurVarFragmentSizeInBits))
5040b57cec5SDimitry Andric         Expr = *E;
5050b57cec5SDimitry Andric       else
50606c3fb27SDimitry Andric         continue;
5070b57cec5SDimitry Andric     }
5080b57cec5SDimitry Andric     auto *NGVE = DIGlobalVariableExpression::get(GVE->getContext(), Var, Expr);
5090b57cec5SDimitry Andric     NGV->addDebugInfo(NGVE);
5100b57cec5SDimitry Andric   }
5110b57cec5SDimitry Andric }
5120b57cec5SDimitry Andric 
5130b57cec5SDimitry Andric /// Perform scalar replacement of aggregates on the specified global variable.
5140b57cec5SDimitry Andric /// This opens the door for other optimizations by exposing the behavior of the
5150b57cec5SDimitry Andric /// program in a more fine-grained way.  We have determined that this
5160b57cec5SDimitry Andric /// transformation is safe already.  We return the first global variable we
5170b57cec5SDimitry Andric /// insert so that the caller can reprocess it.
5180b57cec5SDimitry Andric static GlobalVariable *SRAGlobal(GlobalVariable *GV, const DataLayout &DL) {
5190b57cec5SDimitry Andric   assert(GV->hasLocalLinkage());
5200b57cec5SDimitry Andric 
52104eeddc0SDimitry Andric   // Collect types to split into.
52206c3fb27SDimitry Andric   DenseMap<uint64_t, GlobalPart> Parts;
52306c3fb27SDimitry Andric   if (!collectSRATypes(Parts, GV, DL) || Parts.empty())
5240b57cec5SDimitry Andric     return nullptr;
5250b57cec5SDimitry Andric 
52604eeddc0SDimitry Andric   // Make sure we don't SRA back to the same type.
52706c3fb27SDimitry Andric   if (Parts.size() == 1 && Parts.begin()->second.Ty == GV->getValueType())
52804eeddc0SDimitry Andric     return nullptr;
52904eeddc0SDimitry Andric 
53006c3fb27SDimitry Andric   // Don't perform SRA if we would have to split into many globals. Ignore
53106c3fb27SDimitry Andric   // parts that are either only loaded or only stored, because we expect them
53206c3fb27SDimitry Andric   // to be optimized away.
53306c3fb27SDimitry Andric   unsigned NumParts = count_if(Parts, [](const auto &Pair) {
53406c3fb27SDimitry Andric     return Pair.second.IsLoaded && Pair.second.IsStored;
53506c3fb27SDimitry Andric   });
53606c3fb27SDimitry Andric   if (NumParts > 16)
53704eeddc0SDimitry Andric     return nullptr;
53804eeddc0SDimitry Andric 
53904eeddc0SDimitry Andric   // Sort by offset.
54006c3fb27SDimitry Andric   SmallVector<std::tuple<uint64_t, Type *, Constant *>, 16> TypesVector;
54106c3fb27SDimitry Andric   for (const auto &Pair : Parts) {
54206c3fb27SDimitry Andric     TypesVector.push_back(
54306c3fb27SDimitry Andric         {Pair.first, Pair.second.Ty, Pair.second.Initializer});
54406c3fb27SDimitry Andric   }
545972a253aSDimitry Andric   sort(TypesVector, llvm::less_first());
54604eeddc0SDimitry Andric 
54704eeddc0SDimitry Andric   // Check that the types are non-overlapping.
54804eeddc0SDimitry Andric   uint64_t Offset = 0;
54906c3fb27SDimitry Andric   for (const auto &[OffsetForTy, Ty, _] : TypesVector) {
55004eeddc0SDimitry Andric     // Overlaps with previous type.
55106c3fb27SDimitry Andric     if (OffsetForTy < Offset)
55204eeddc0SDimitry Andric       return nullptr;
55304eeddc0SDimitry Andric 
55406c3fb27SDimitry Andric     Offset = OffsetForTy + DL.getTypeAllocSize(Ty);
55504eeddc0SDimitry Andric   }
55604eeddc0SDimitry Andric 
55704eeddc0SDimitry Andric   // Some accesses go beyond the end of the global, don't bother.
55804eeddc0SDimitry Andric   if (Offset > DL.getTypeAllocSize(GV->getValueType()))
55904eeddc0SDimitry Andric     return nullptr;
56004eeddc0SDimitry Andric 
5610b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "PERFORMING GLOBAL SRA ON: " << *GV << "\n");
5620b57cec5SDimitry Andric 
56304eeddc0SDimitry Andric   // Get the alignment of the global, either explicit or target-specific.
56404eeddc0SDimitry Andric   Align StartAlignment =
56504eeddc0SDimitry Andric       DL.getValueOrABITypeAlignment(GV->getAlign(), GV->getValueType());
56604eeddc0SDimitry Andric   uint64_t VarSize = DL.getTypeSizeInBits(GV->getValueType());
5670b57cec5SDimitry Andric 
56804eeddc0SDimitry Andric   // Create replacement globals.
56904eeddc0SDimitry Andric   DenseMap<uint64_t, GlobalVariable *> NewGlobals;
57004eeddc0SDimitry Andric   unsigned NameSuffix = 0;
57106c3fb27SDimitry Andric   for (auto &[OffsetForTy, Ty, Initializer] : TypesVector) {
57204eeddc0SDimitry Andric     GlobalVariable *NGV = new GlobalVariable(
57304eeddc0SDimitry Andric         *GV->getParent(), Ty, false, GlobalVariable::InternalLinkage,
57406c3fb27SDimitry Andric         Initializer, GV->getName() + "." + Twine(NameSuffix++), GV,
57504eeddc0SDimitry Andric         GV->getThreadLocalMode(), GV->getAddressSpace());
57604eeddc0SDimitry Andric     NGV->copyAttributesFrom(GV);
57706c3fb27SDimitry Andric     NewGlobals.insert({OffsetForTy, NGV});
5780b57cec5SDimitry Andric 
57904eeddc0SDimitry Andric     // Calculate the known alignment of the field.  If the original aggregate
58004eeddc0SDimitry Andric     // had 256 byte alignment for example, something might depend on that:
58104eeddc0SDimitry Andric     // propagate info to each field.
58206c3fb27SDimitry Andric     Align NewAlign = commonAlignment(StartAlignment, OffsetForTy);
58304eeddc0SDimitry Andric     if (NewAlign > DL.getABITypeAlign(Ty))
58404eeddc0SDimitry Andric       NGV->setAlignment(NewAlign);
5850b57cec5SDimitry Andric 
58604eeddc0SDimitry Andric     // Copy over the debug info for the variable.
58706c3fb27SDimitry Andric     transferSRADebugInfo(GV, NGV, OffsetForTy * 8,
58806c3fb27SDimitry Andric                          DL.getTypeAllocSizeInBits(Ty), VarSize);
58904eeddc0SDimitry Andric   }
5900b57cec5SDimitry Andric 
59104eeddc0SDimitry Andric   // Replace uses of the original global with uses of the new global.
59204eeddc0SDimitry Andric   SmallVector<Value *, 16> Worklist;
59304eeddc0SDimitry Andric   SmallPtrSet<Value *, 16> Visited;
59404eeddc0SDimitry Andric   SmallVector<WeakTrackingVH, 16> DeadInsts;
59504eeddc0SDimitry Andric   auto AppendUsers = [&](Value *V) {
59604eeddc0SDimitry Andric     for (User *U : V->users())
59704eeddc0SDimitry Andric       if (Visited.insert(U).second)
59804eeddc0SDimitry Andric         Worklist.push_back(U);
59904eeddc0SDimitry Andric   };
60004eeddc0SDimitry Andric   AppendUsers(GV);
60104eeddc0SDimitry Andric   while (!Worklist.empty()) {
60204eeddc0SDimitry Andric     Value *V = Worklist.pop_back_val();
60304eeddc0SDimitry Andric     if (isa<BitCastOperator>(V) || isa<AddrSpaceCastOperator>(V) ||
60404eeddc0SDimitry Andric         isa<GEPOperator>(V)) {
60504eeddc0SDimitry Andric       AppendUsers(V);
60604eeddc0SDimitry Andric       if (isa<Instruction>(V))
60704eeddc0SDimitry Andric         DeadInsts.push_back(V);
60804eeddc0SDimitry Andric       continue;
60904eeddc0SDimitry Andric     }
61004eeddc0SDimitry Andric 
61104eeddc0SDimitry Andric     if (Value *Ptr = getLoadStorePointerOperand(V)) {
61204eeddc0SDimitry Andric       APInt Offset(DL.getIndexTypeSizeInBits(Ptr->getType()), 0);
61304eeddc0SDimitry Andric       Ptr = Ptr->stripAndAccumulateConstantOffsets(DL, Offset,
61404eeddc0SDimitry Andric                                                    /* AllowNonInbounds */ true);
61504eeddc0SDimitry Andric       assert(Ptr == GV && "Load/store must be from/to global");
61604eeddc0SDimitry Andric       GlobalVariable *NGV = NewGlobals[Offset.getZExtValue()];
61704eeddc0SDimitry Andric       assert(NGV && "Must have replacement global for this offset");
61804eeddc0SDimitry Andric 
61904eeddc0SDimitry Andric       // Update the pointer operand and recalculate alignment.
62004eeddc0SDimitry Andric       Align PrefAlign = DL.getPrefTypeAlign(getLoadStoreType(V));
62104eeddc0SDimitry Andric       Align NewAlign =
62204eeddc0SDimitry Andric           getOrEnforceKnownAlignment(NGV, PrefAlign, DL, cast<Instruction>(V));
62304eeddc0SDimitry Andric 
62404eeddc0SDimitry Andric       if (auto *LI = dyn_cast<LoadInst>(V)) {
62504eeddc0SDimitry Andric         LI->setOperand(0, NGV);
62604eeddc0SDimitry Andric         LI->setAlignment(NewAlign);
6270b57cec5SDimitry Andric       } else {
62804eeddc0SDimitry Andric         auto *SI = cast<StoreInst>(V);
62904eeddc0SDimitry Andric         SI->setOperand(1, NGV);
63004eeddc0SDimitry Andric         SI->setAlignment(NewAlign);
6310b57cec5SDimitry Andric       }
63204eeddc0SDimitry Andric       continue;
633fe6060f1SDimitry Andric     }
634fe6060f1SDimitry Andric 
63504eeddc0SDimitry Andric     assert(isa<Constant>(V) && isSafeToDestroyConstant(cast<Constant>(V)) &&
63604eeddc0SDimitry Andric            "Other users can only be dead constants");
6370b57cec5SDimitry Andric   }
6380b57cec5SDimitry Andric 
63904eeddc0SDimitry Andric   // Delete old instructions and global.
64004eeddc0SDimitry Andric   RecursivelyDeleteTriviallyDeadInstructions(DeadInsts);
64104eeddc0SDimitry Andric   GV->removeDeadConstantUsers();
64204eeddc0SDimitry Andric   GV->eraseFromParent();
6430b57cec5SDimitry Andric   ++NumSRA;
6440b57cec5SDimitry Andric 
645480093f4SDimitry Andric   assert(NewGlobals.size() > 0);
646480093f4SDimitry Andric   return NewGlobals.begin()->second;
6470b57cec5SDimitry Andric }
6480b57cec5SDimitry Andric 
6490b57cec5SDimitry Andric /// Return true if all users of the specified value will trap if the value is
6500b57cec5SDimitry Andric /// dynamically null.  PHIs keeps track of any phi nodes we've seen to avoid
6510b57cec5SDimitry Andric /// reprocessing them.
6520b57cec5SDimitry Andric static bool AllUsesOfValueWillTrapIfNull(const Value *V,
6530b57cec5SDimitry Andric                                         SmallPtrSetImpl<const PHINode*> &PHIs) {
6540b57cec5SDimitry Andric   for (const User *U : V->users()) {
6550b57cec5SDimitry Andric     if (const Instruction *I = dyn_cast<Instruction>(U)) {
6560b57cec5SDimitry Andric       // If null pointer is considered valid, then all uses are non-trapping.
6570b57cec5SDimitry Andric       // Non address-space 0 globals have already been pruned by the caller.
6580b57cec5SDimitry Andric       if (NullPointerIsDefined(I->getFunction()))
6590b57cec5SDimitry Andric         return false;
6600b57cec5SDimitry Andric     }
6610b57cec5SDimitry Andric     if (isa<LoadInst>(U)) {
6620b57cec5SDimitry Andric       // Will trap.
6630b57cec5SDimitry Andric     } else if (const StoreInst *SI = dyn_cast<StoreInst>(U)) {
6640b57cec5SDimitry Andric       if (SI->getOperand(0) == V) {
6650b57cec5SDimitry Andric         return false;  // Storing the value.
6660b57cec5SDimitry Andric       }
6670b57cec5SDimitry Andric     } else if (const CallInst *CI = dyn_cast<CallInst>(U)) {
6685ffd83dbSDimitry Andric       if (CI->getCalledOperand() != V) {
6690b57cec5SDimitry Andric         return false;  // Not calling the ptr
6700b57cec5SDimitry Andric       }
6710b57cec5SDimitry Andric     } else if (const InvokeInst *II = dyn_cast<InvokeInst>(U)) {
6725ffd83dbSDimitry Andric       if (II->getCalledOperand() != V) {
6730b57cec5SDimitry Andric         return false;  // Not calling the ptr
6740b57cec5SDimitry Andric       }
67506c3fb27SDimitry Andric     } else if (const AddrSpaceCastInst *CI = dyn_cast<AddrSpaceCastInst>(U)) {
67606c3fb27SDimitry Andric       if (!AllUsesOfValueWillTrapIfNull(CI, PHIs))
67706c3fb27SDimitry Andric         return false;
6780b57cec5SDimitry Andric     } else if (const GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(U)) {
6790b57cec5SDimitry Andric       if (!AllUsesOfValueWillTrapIfNull(GEPI, PHIs)) return false;
6800b57cec5SDimitry Andric     } else if (const PHINode *PN = dyn_cast<PHINode>(U)) {
6810b57cec5SDimitry Andric       // If we've already seen this phi node, ignore it, it has already been
6820b57cec5SDimitry Andric       // checked.
6830b57cec5SDimitry Andric       if (PHIs.insert(PN).second && !AllUsesOfValueWillTrapIfNull(PN, PHIs))
6840b57cec5SDimitry Andric         return false;
685fe6060f1SDimitry Andric     } else if (isa<ICmpInst>(U) &&
686fe6060f1SDimitry Andric                !ICmpInst::isSigned(cast<ICmpInst>(U)->getPredicate()) &&
687fe6060f1SDimitry Andric                isa<LoadInst>(U->getOperand(0)) &&
688fe6060f1SDimitry Andric                isa<ConstantPointerNull>(U->getOperand(1))) {
689349cc55cSDimitry Andric       assert(isa<GlobalValue>(cast<LoadInst>(U->getOperand(0))
690349cc55cSDimitry Andric                                   ->getPointerOperand()
691349cc55cSDimitry Andric                                   ->stripPointerCasts()) &&
692fe6060f1SDimitry Andric              "Should be GlobalVariable");
693fe6060f1SDimitry Andric       // This and only this kind of non-signed ICmpInst is to be replaced with
694fe6060f1SDimitry Andric       // the comparing of the value of the created global init bool later in
69504eeddc0SDimitry Andric       // optimizeGlobalAddressOfAllocation for the global variable.
6960b57cec5SDimitry Andric     } else {
6970b57cec5SDimitry Andric       return false;
6980b57cec5SDimitry Andric     }
6990b57cec5SDimitry Andric   }
7000b57cec5SDimitry Andric   return true;
7010b57cec5SDimitry Andric }
7020b57cec5SDimitry Andric 
7030b57cec5SDimitry Andric /// Return true if all uses of any loads from GV will trap if the loaded value
7040b57cec5SDimitry Andric /// is null.  Note that this also permits comparisons of the loaded value
7050b57cec5SDimitry Andric /// against null, as a special case.
706349cc55cSDimitry Andric static bool allUsesOfLoadedValueWillTrapIfNull(const GlobalVariable *GV) {
707349cc55cSDimitry Andric   SmallVector<const Value *, 4> Worklist;
708349cc55cSDimitry Andric   Worklist.push_back(GV);
709349cc55cSDimitry Andric   while (!Worklist.empty()) {
710349cc55cSDimitry Andric     const Value *P = Worklist.pop_back_val();
711bdd1243dSDimitry Andric     for (const auto *U : P->users()) {
712349cc55cSDimitry Andric       if (auto *LI = dyn_cast<LoadInst>(U)) {
7130b57cec5SDimitry Andric         SmallPtrSet<const PHINode *, 8> PHIs;
7140b57cec5SDimitry Andric         if (!AllUsesOfValueWillTrapIfNull(LI, PHIs))
7150b57cec5SDimitry Andric           return false;
716349cc55cSDimitry Andric       } else if (auto *SI = dyn_cast<StoreInst>(U)) {
7170b57cec5SDimitry Andric         // Ignore stores to the global.
718349cc55cSDimitry Andric         if (SI->getPointerOperand() != P)
719349cc55cSDimitry Andric           return false;
720349cc55cSDimitry Andric       } else if (auto *CE = dyn_cast<ConstantExpr>(U)) {
721349cc55cSDimitry Andric         if (CE->stripPointerCasts() != GV)
722349cc55cSDimitry Andric           return false;
723349cc55cSDimitry Andric         // Check further the ConstantExpr.
724349cc55cSDimitry Andric         Worklist.push_back(CE);
7250b57cec5SDimitry Andric       } else {
7260b57cec5SDimitry Andric         // We don't know or understand this user, bail out.
7270b57cec5SDimitry Andric         return false;
7280b57cec5SDimitry Andric       }
729349cc55cSDimitry Andric     }
730349cc55cSDimitry Andric   }
731349cc55cSDimitry Andric 
7320b57cec5SDimitry Andric   return true;
7330b57cec5SDimitry Andric }
7340b57cec5SDimitry Andric 
735349cc55cSDimitry Andric /// Get all the loads/store uses for global variable \p GV.
736349cc55cSDimitry Andric static void allUsesOfLoadAndStores(GlobalVariable *GV,
737349cc55cSDimitry Andric                                    SmallVector<Value *, 4> &Uses) {
738349cc55cSDimitry Andric   SmallVector<Value *, 4> Worklist;
739349cc55cSDimitry Andric   Worklist.push_back(GV);
740349cc55cSDimitry Andric   while (!Worklist.empty()) {
741349cc55cSDimitry Andric     auto *P = Worklist.pop_back_val();
742349cc55cSDimitry Andric     for (auto *U : P->users()) {
743349cc55cSDimitry Andric       if (auto *CE = dyn_cast<ConstantExpr>(U)) {
744349cc55cSDimitry Andric         Worklist.push_back(CE);
745349cc55cSDimitry Andric         continue;
746349cc55cSDimitry Andric       }
747349cc55cSDimitry Andric 
748349cc55cSDimitry Andric       assert((isa<LoadInst>(U) || isa<StoreInst>(U)) &&
749349cc55cSDimitry Andric              "Expect only load or store instructions");
750349cc55cSDimitry Andric       Uses.push_back(U);
751349cc55cSDimitry Andric     }
752349cc55cSDimitry Andric   }
753349cc55cSDimitry Andric }
754349cc55cSDimitry Andric 
7550b57cec5SDimitry Andric static bool OptimizeAwayTrappingUsesOfValue(Value *V, Constant *NewV) {
7560b57cec5SDimitry Andric   bool Changed = false;
7570b57cec5SDimitry Andric   for (auto UI = V->user_begin(), E = V->user_end(); UI != E; ) {
7580b57cec5SDimitry Andric     Instruction *I = cast<Instruction>(*UI++);
7590b57cec5SDimitry Andric     // Uses are non-trapping if null pointer is considered valid.
7600b57cec5SDimitry Andric     // Non address-space 0 globals are already pruned by the caller.
7610b57cec5SDimitry Andric     if (NullPointerIsDefined(I->getFunction()))
7620b57cec5SDimitry Andric       return false;
7630b57cec5SDimitry Andric     if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
7640b57cec5SDimitry Andric       LI->setOperand(0, NewV);
7650b57cec5SDimitry Andric       Changed = true;
7660b57cec5SDimitry Andric     } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
7670b57cec5SDimitry Andric       if (SI->getOperand(1) == V) {
7680b57cec5SDimitry Andric         SI->setOperand(1, NewV);
7690b57cec5SDimitry Andric         Changed = true;
7700b57cec5SDimitry Andric       }
7710b57cec5SDimitry Andric     } else if (isa<CallInst>(I) || isa<InvokeInst>(I)) {
7725ffd83dbSDimitry Andric       CallBase *CB = cast<CallBase>(I);
7735ffd83dbSDimitry Andric       if (CB->getCalledOperand() == V) {
7740b57cec5SDimitry Andric         // Calling through the pointer!  Turn into a direct call, but be careful
7750b57cec5SDimitry Andric         // that the pointer is not also being passed as an argument.
7765ffd83dbSDimitry Andric         CB->setCalledOperand(NewV);
7770b57cec5SDimitry Andric         Changed = true;
7780b57cec5SDimitry Andric         bool PassedAsArg = false;
7795ffd83dbSDimitry Andric         for (unsigned i = 0, e = CB->arg_size(); i != e; ++i)
7805ffd83dbSDimitry Andric           if (CB->getArgOperand(i) == V) {
7810b57cec5SDimitry Andric             PassedAsArg = true;
7825ffd83dbSDimitry Andric             CB->setArgOperand(i, NewV);
7830b57cec5SDimitry Andric           }
7840b57cec5SDimitry Andric 
7850b57cec5SDimitry Andric         if (PassedAsArg) {
7860b57cec5SDimitry Andric           // Being passed as an argument also.  Be careful to not invalidate UI!
7870b57cec5SDimitry Andric           UI = V->user_begin();
7880b57cec5SDimitry Andric         }
7890b57cec5SDimitry Andric       }
79006c3fb27SDimitry Andric     } else if (AddrSpaceCastInst *CI = dyn_cast<AddrSpaceCastInst>(I)) {
79106c3fb27SDimitry Andric       Changed |= OptimizeAwayTrappingUsesOfValue(
79206c3fb27SDimitry Andric           CI, ConstantExpr::getAddrSpaceCast(NewV, CI->getType()));
7930b57cec5SDimitry Andric       if (CI->use_empty()) {
7940b57cec5SDimitry Andric         Changed = true;
7950b57cec5SDimitry Andric         CI->eraseFromParent();
7960b57cec5SDimitry Andric       }
7970b57cec5SDimitry Andric     } else if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(I)) {
7980b57cec5SDimitry Andric       // Should handle GEP here.
7990b57cec5SDimitry Andric       SmallVector<Constant*, 8> Idxs;
8000b57cec5SDimitry Andric       Idxs.reserve(GEPI->getNumOperands()-1);
8010b57cec5SDimitry Andric       for (User::op_iterator i = GEPI->op_begin() + 1, e = GEPI->op_end();
8020b57cec5SDimitry Andric            i != e; ++i)
8030b57cec5SDimitry Andric         if (Constant *C = dyn_cast<Constant>(*i))
8040b57cec5SDimitry Andric           Idxs.push_back(C);
8050b57cec5SDimitry Andric         else
8060b57cec5SDimitry Andric           break;
8070b57cec5SDimitry Andric       if (Idxs.size() == GEPI->getNumOperands()-1)
8080b57cec5SDimitry Andric         Changed |= OptimizeAwayTrappingUsesOfValue(
8090b57cec5SDimitry Andric             GEPI, ConstantExpr::getGetElementPtr(GEPI->getSourceElementType(),
8100b57cec5SDimitry Andric                                                  NewV, Idxs));
8110b57cec5SDimitry Andric       if (GEPI->use_empty()) {
8120b57cec5SDimitry Andric         Changed = true;
8130b57cec5SDimitry Andric         GEPI->eraseFromParent();
8140b57cec5SDimitry Andric       }
8150b57cec5SDimitry Andric     }
8160b57cec5SDimitry Andric   }
8170b57cec5SDimitry Andric 
8180b57cec5SDimitry Andric   return Changed;
8190b57cec5SDimitry Andric }
8200b57cec5SDimitry Andric 
8210b57cec5SDimitry Andric /// The specified global has only one non-null value stored into it.  If there
8220b57cec5SDimitry Andric /// are uses of the loaded value that would trap if the loaded value is
8230b57cec5SDimitry Andric /// dynamically null, then we know that they cannot be reachable with a null
8240b57cec5SDimitry Andric /// optimize away the load.
8258bcb0991SDimitry Andric static bool OptimizeAwayTrappingUsesOfLoads(
8268bcb0991SDimitry Andric     GlobalVariable *GV, Constant *LV, const DataLayout &DL,
8278bcb0991SDimitry Andric     function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
8280b57cec5SDimitry Andric   bool Changed = false;
8290b57cec5SDimitry Andric 
8300b57cec5SDimitry Andric   // Keep track of whether we are able to remove all the uses of the global
8310b57cec5SDimitry Andric   // other than the store that defines it.
8320b57cec5SDimitry Andric   bool AllNonStoreUsesGone = true;
8330b57cec5SDimitry Andric 
8340b57cec5SDimitry Andric   // Replace all uses of loads with uses of uses of the stored value.
835349cc55cSDimitry Andric   for (User *GlobalUser : llvm::make_early_inc_range(GV->users())) {
8360b57cec5SDimitry Andric     if (LoadInst *LI = dyn_cast<LoadInst>(GlobalUser)) {
8370b57cec5SDimitry Andric       Changed |= OptimizeAwayTrappingUsesOfValue(LI, LV);
8380b57cec5SDimitry Andric       // If we were able to delete all uses of the loads
8390b57cec5SDimitry Andric       if (LI->use_empty()) {
8400b57cec5SDimitry Andric         LI->eraseFromParent();
8410b57cec5SDimitry Andric         Changed = true;
8420b57cec5SDimitry Andric       } else {
8430b57cec5SDimitry Andric         AllNonStoreUsesGone = false;
8440b57cec5SDimitry Andric       }
8450b57cec5SDimitry Andric     } else if (isa<StoreInst>(GlobalUser)) {
8460b57cec5SDimitry Andric       // Ignore the store that stores "LV" to the global.
8470b57cec5SDimitry Andric       assert(GlobalUser->getOperand(1) == GV &&
8480b57cec5SDimitry Andric              "Must be storing *to* the global");
8490b57cec5SDimitry Andric     } else {
8500b57cec5SDimitry Andric       AllNonStoreUsesGone = false;
8510b57cec5SDimitry Andric 
8520b57cec5SDimitry Andric       // If we get here we could have other crazy uses that are transitively
8530b57cec5SDimitry Andric       // loaded.
8540b57cec5SDimitry Andric       assert((isa<PHINode>(GlobalUser) || isa<SelectInst>(GlobalUser) ||
8550b57cec5SDimitry Andric               isa<ConstantExpr>(GlobalUser) || isa<CmpInst>(GlobalUser) ||
8560b57cec5SDimitry Andric               isa<BitCastInst>(GlobalUser) ||
85706c3fb27SDimitry Andric               isa<GetElementPtrInst>(GlobalUser) ||
85806c3fb27SDimitry Andric               isa<AddrSpaceCastInst>(GlobalUser)) &&
8590b57cec5SDimitry Andric              "Only expect load and stores!");
8600b57cec5SDimitry Andric     }
8610b57cec5SDimitry Andric   }
8620b57cec5SDimitry Andric 
8630b57cec5SDimitry Andric   if (Changed) {
8640b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "OPTIMIZED LOADS FROM STORED ONCE POINTER: " << *GV
8650b57cec5SDimitry Andric                       << "\n");
8660b57cec5SDimitry Andric     ++NumGlobUses;
8670b57cec5SDimitry Andric   }
8680b57cec5SDimitry Andric 
8690b57cec5SDimitry Andric   // If we nuked all of the loads, then none of the stores are needed either,
8700b57cec5SDimitry Andric   // nor is the global.
8710b57cec5SDimitry Andric   if (AllNonStoreUsesGone) {
8720b57cec5SDimitry Andric     if (isLeakCheckerRoot(GV)) {
8738bcb0991SDimitry Andric       Changed |= CleanupPointerRootUsers(GV, GetTLI);
8740b57cec5SDimitry Andric     } else {
8750b57cec5SDimitry Andric       Changed = true;
8764824e7fdSDimitry Andric       CleanupConstantGlobalUsers(GV, DL);
8770b57cec5SDimitry Andric     }
8780b57cec5SDimitry Andric     if (GV->use_empty()) {
8790b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "  *** GLOBAL NOW DEAD!\n");
8800b57cec5SDimitry Andric       Changed = true;
8810b57cec5SDimitry Andric       GV->eraseFromParent();
8820b57cec5SDimitry Andric       ++NumDeleted;
8830b57cec5SDimitry Andric     }
8840b57cec5SDimitry Andric   }
8850b57cec5SDimitry Andric   return Changed;
8860b57cec5SDimitry Andric }
8870b57cec5SDimitry Andric 
8880b57cec5SDimitry Andric /// Walk the use list of V, constant folding all of the instructions that are
8890b57cec5SDimitry Andric /// foldable.
8900b57cec5SDimitry Andric static void ConstantPropUsersOf(Value *V, const DataLayout &DL,
8910b57cec5SDimitry Andric                                 TargetLibraryInfo *TLI) {
8920b57cec5SDimitry Andric   for (Value::user_iterator UI = V->user_begin(), E = V->user_end(); UI != E; )
8930b57cec5SDimitry Andric     if (Instruction *I = dyn_cast<Instruction>(*UI++))
8940b57cec5SDimitry Andric       if (Constant *NewC = ConstantFoldInstruction(I, DL, TLI)) {
8950b57cec5SDimitry Andric         I->replaceAllUsesWith(NewC);
8960b57cec5SDimitry Andric 
8970b57cec5SDimitry Andric         // Advance UI to the next non-I use to avoid invalidating it!
8980b57cec5SDimitry Andric         // Instructions could multiply use V.
8990b57cec5SDimitry Andric         while (UI != E && *UI == I)
9000b57cec5SDimitry Andric           ++UI;
9010b57cec5SDimitry Andric         if (isInstructionTriviallyDead(I, TLI))
9020b57cec5SDimitry Andric           I->eraseFromParent();
9030b57cec5SDimitry Andric       }
9040b57cec5SDimitry Andric }
9050b57cec5SDimitry Andric 
9060b57cec5SDimitry Andric /// This function takes the specified global variable, and transforms the
9070b57cec5SDimitry Andric /// program as if it always contained the result of the specified malloc.
9080b57cec5SDimitry Andric /// Because it is always the result of the specified malloc, there is no reason
9090b57cec5SDimitry Andric /// to actually DO the malloc.  Instead, turn the malloc into a global, and any
9100b57cec5SDimitry Andric /// loads of GV as uses of the new global.
9110b57cec5SDimitry Andric static GlobalVariable *
91204eeddc0SDimitry Andric OptimizeGlobalAddressOfAllocation(GlobalVariable *GV, CallInst *CI,
91304eeddc0SDimitry Andric                                   uint64_t AllocSize, Constant *InitVal,
91404eeddc0SDimitry Andric                                   const DataLayout &DL,
9150b57cec5SDimitry Andric                                   TargetLibraryInfo *TLI) {
9160b57cec5SDimitry Andric   LLVM_DEBUG(errs() << "PROMOTING GLOBAL: " << *GV << "  CALL = " << *CI
9170b57cec5SDimitry Andric                     << '\n');
9180b57cec5SDimitry Andric 
91904eeddc0SDimitry Andric   // Create global of type [AllocSize x i8].
92004eeddc0SDimitry Andric   Type *GlobalType = ArrayType::get(Type::getInt8Ty(GV->getContext()),
92104eeddc0SDimitry Andric                                     AllocSize);
9220b57cec5SDimitry Andric 
92304eeddc0SDimitry Andric   // Create the new global variable.  The contents of the allocated memory is
92404eeddc0SDimitry Andric   // undefined initially, so initialize with an undef value.
9250b57cec5SDimitry Andric   GlobalVariable *NewGV = new GlobalVariable(
9260b57cec5SDimitry Andric       *GV->getParent(), GlobalType, false, GlobalValue::InternalLinkage,
9270b57cec5SDimitry Andric       UndefValue::get(GlobalType), GV->getName() + ".body", nullptr,
9280b57cec5SDimitry Andric       GV->getThreadLocalMode());
9290b57cec5SDimitry Andric 
93004eeddc0SDimitry Andric   // Initialize the global at the point of the original call.  Note that this
93104eeddc0SDimitry Andric   // is a different point from the initialization referred to below for the
93204eeddc0SDimitry Andric   // nullability handling.  Sublety: We have not proven the original global was
93304eeddc0SDimitry Andric   // only initialized once.  As such, we can not fold this into the initializer
93404eeddc0SDimitry Andric   // of the new global as may need to re-init the storage multiple times.
93504eeddc0SDimitry Andric   if (!isa<UndefValue>(InitVal)) {
93604eeddc0SDimitry Andric     IRBuilder<> Builder(CI->getNextNode());
93704eeddc0SDimitry Andric     // TODO: Use alignment above if align!=1
938bdd1243dSDimitry Andric     Builder.CreateMemSet(NewGV, InitVal, AllocSize, std::nullopt);
93904eeddc0SDimitry Andric   }
94004eeddc0SDimitry Andric 
94104eeddc0SDimitry Andric   // Update users of the allocation to use the new global instead.
9425f757f3fSDimitry Andric   CI->replaceAllUsesWith(NewGV);
9430b57cec5SDimitry Andric 
9440b57cec5SDimitry Andric   // If there is a comparison against null, we will insert a global bool to
9450b57cec5SDimitry Andric   // keep track of whether the global was initialized yet or not.
9460b57cec5SDimitry Andric   GlobalVariable *InitBool =
9470b57cec5SDimitry Andric     new GlobalVariable(Type::getInt1Ty(GV->getContext()), false,
9480b57cec5SDimitry Andric                        GlobalValue::InternalLinkage,
9490b57cec5SDimitry Andric                        ConstantInt::getFalse(GV->getContext()),
9500b57cec5SDimitry Andric                        GV->getName()+".init", GV->getThreadLocalMode());
9510b57cec5SDimitry Andric   bool InitBoolUsed = false;
9520b57cec5SDimitry Andric 
953349cc55cSDimitry Andric   // Loop over all instruction uses of GV, processing them in turn.
954349cc55cSDimitry Andric   SmallVector<Value *, 4> Guses;
955349cc55cSDimitry Andric   allUsesOfLoadAndStores(GV, Guses);
956349cc55cSDimitry Andric   for (auto *U : Guses) {
957349cc55cSDimitry Andric     if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
958fe6060f1SDimitry Andric       // The global is initialized when the store to it occurs. If the stored
959fe6060f1SDimitry Andric       // value is null value, the global bool is set to false, otherwise true.
960fe6060f1SDimitry Andric       new StoreInst(ConstantInt::getBool(
961fe6060f1SDimitry Andric                         GV->getContext(),
962fe6060f1SDimitry Andric                         !isa<ConstantPointerNull>(SI->getValueOperand())),
963fe6060f1SDimitry Andric                     InitBool, false, Align(1), SI->getOrdering(),
964*0fca6ea1SDimitry Andric                     SI->getSyncScopeID(), SI->getIterator());
9650b57cec5SDimitry Andric       SI->eraseFromParent();
9660b57cec5SDimitry Andric       continue;
9670b57cec5SDimitry Andric     }
9680b57cec5SDimitry Andric 
969349cc55cSDimitry Andric     LoadInst *LI = cast<LoadInst>(U);
9700b57cec5SDimitry Andric     while (!LI->use_empty()) {
9710b57cec5SDimitry Andric       Use &LoadUse = *LI->use_begin();
9720b57cec5SDimitry Andric       ICmpInst *ICI = dyn_cast<ICmpInst>(LoadUse.getUser());
9730b57cec5SDimitry Andric       if (!ICI) {
9745f757f3fSDimitry Andric         LoadUse.set(NewGV);
9750b57cec5SDimitry Andric         continue;
9760b57cec5SDimitry Andric       }
9770b57cec5SDimitry Andric 
9780b57cec5SDimitry Andric       // Replace the cmp X, 0 with a use of the bool value.
9790b57cec5SDimitry Andric       Value *LV = new LoadInst(InitBool->getValueType(), InitBool,
9805ffd83dbSDimitry Andric                                InitBool->getName() + ".val", false, Align(1),
981*0fca6ea1SDimitry Andric                                LI->getOrdering(), LI->getSyncScopeID(),
982*0fca6ea1SDimitry Andric                                LI->getIterator());
9830b57cec5SDimitry Andric       InitBoolUsed = true;
9840b57cec5SDimitry Andric       switch (ICI->getPredicate()) {
9850b57cec5SDimitry Andric       default: llvm_unreachable("Unknown ICmp Predicate!");
986fe6060f1SDimitry Andric       case ICmpInst::ICMP_ULT: // X < null -> always false
9870b57cec5SDimitry Andric         LV = ConstantInt::getFalse(GV->getContext());
9880b57cec5SDimitry Andric         break;
989fe6060f1SDimitry Andric       case ICmpInst::ICMP_UGE: // X >= null -> always true
990fe6060f1SDimitry Andric         LV = ConstantInt::getTrue(GV->getContext());
991fe6060f1SDimitry Andric         break;
9920b57cec5SDimitry Andric       case ICmpInst::ICMP_ULE:
9930b57cec5SDimitry Andric       case ICmpInst::ICMP_EQ:
994*0fca6ea1SDimitry Andric         LV = BinaryOperator::CreateNot(LV, "notinit", ICI->getIterator());
9950b57cec5SDimitry Andric         break;
9960b57cec5SDimitry Andric       case ICmpInst::ICMP_NE:
9970b57cec5SDimitry Andric       case ICmpInst::ICMP_UGT:
9980b57cec5SDimitry Andric         break;  // no change.
9990b57cec5SDimitry Andric       }
10000b57cec5SDimitry Andric       ICI->replaceAllUsesWith(LV);
10010b57cec5SDimitry Andric       ICI->eraseFromParent();
10020b57cec5SDimitry Andric     }
10030b57cec5SDimitry Andric     LI->eraseFromParent();
10040b57cec5SDimitry Andric   }
10050b57cec5SDimitry Andric 
10060b57cec5SDimitry Andric   // If the initialization boolean was used, insert it, otherwise delete it.
10070b57cec5SDimitry Andric   if (!InitBoolUsed) {
10080b57cec5SDimitry Andric     while (!InitBool->use_empty())  // Delete initializations
10090b57cec5SDimitry Andric       cast<StoreInst>(InitBool->user_back())->eraseFromParent();
10100b57cec5SDimitry Andric     delete InitBool;
10110b57cec5SDimitry Andric   } else
101206c3fb27SDimitry Andric     GV->getParent()->insertGlobalVariable(GV->getIterator(), InitBool);
10130b57cec5SDimitry Andric 
101404eeddc0SDimitry Andric   // Now the GV is dead, nuke it and the allocation..
10150b57cec5SDimitry Andric   GV->eraseFromParent();
10160b57cec5SDimitry Andric   CI->eraseFromParent();
10170b57cec5SDimitry Andric 
10180b57cec5SDimitry Andric   // To further other optimizations, loop over all users of NewGV and try to
10190b57cec5SDimitry Andric   // constant prop them.  This will promote GEP instructions with constant
10200b57cec5SDimitry Andric   // indices into GEP constant-exprs, which will allow global-opt to hack on it.
10215f757f3fSDimitry Andric   ConstantPropUsersOf(NewGV, DL, TLI);
10220b57cec5SDimitry Andric 
10230b57cec5SDimitry Andric   return NewGV;
10240b57cec5SDimitry Andric }
10250b57cec5SDimitry Andric 
1026349cc55cSDimitry Andric /// Scan the use-list of GV checking to make sure that there are no complex uses
1027349cc55cSDimitry Andric /// of GV.  We permit simple things like dereferencing the pointer, but not
10280b57cec5SDimitry Andric /// storing through the address, unless it is to the specified global.
1029fe6060f1SDimitry Andric static bool
1030349cc55cSDimitry Andric valueIsOnlyUsedLocallyOrStoredToOneGlobal(const CallInst *CI,
1031fe6060f1SDimitry Andric                                           const GlobalVariable *GV) {
1032349cc55cSDimitry Andric   SmallPtrSet<const Value *, 4> Visited;
1033349cc55cSDimitry Andric   SmallVector<const Value *, 4> Worklist;
1034349cc55cSDimitry Andric   Worklist.push_back(CI);
10350b57cec5SDimitry Andric 
1036349cc55cSDimitry Andric   while (!Worklist.empty()) {
1037349cc55cSDimitry Andric     const Value *V = Worklist.pop_back_val();
1038349cc55cSDimitry Andric     if (!Visited.insert(V).second)
1039349cc55cSDimitry Andric       continue;
1040349cc55cSDimitry Andric 
1041349cc55cSDimitry Andric     for (const Use &VUse : V->uses()) {
1042349cc55cSDimitry Andric       const User *U = VUse.getUser();
1043349cc55cSDimitry Andric       if (isa<LoadInst>(U) || isa<CmpInst>(U))
10440b57cec5SDimitry Andric         continue; // Fine, ignore.
10450b57cec5SDimitry Andric 
1046349cc55cSDimitry Andric       if (auto *SI = dyn_cast<StoreInst>(U)) {
1047349cc55cSDimitry Andric         if (SI->getValueOperand() == V &&
1048349cc55cSDimitry Andric             SI->getPointerOperand()->stripPointerCasts() != GV)
1049349cc55cSDimitry Andric           return false; // Storing the pointer not into GV... bad.
10500b57cec5SDimitry Andric         continue; // Otherwise, storing through it, or storing into GV... fine.
10510b57cec5SDimitry Andric       }
10520b57cec5SDimitry Andric 
1053349cc55cSDimitry Andric       if (auto *BCI = dyn_cast<BitCastInst>(U)) {
1054349cc55cSDimitry Andric         Worklist.push_back(BCI);
1055349cc55cSDimitry Andric         continue;
1056349cc55cSDimitry Andric       }
1057349cc55cSDimitry Andric 
1058349cc55cSDimitry Andric       if (auto *GEPI = dyn_cast<GetElementPtrInst>(U)) {
1059349cc55cSDimitry Andric         Worklist.push_back(GEPI);
10600b57cec5SDimitry Andric         continue;
10610b57cec5SDimitry Andric       }
10620b57cec5SDimitry Andric 
10630b57cec5SDimitry Andric       return false;
10640b57cec5SDimitry Andric     }
1065349cc55cSDimitry Andric   }
1066349cc55cSDimitry Andric 
10670b57cec5SDimitry Andric   return true;
10680b57cec5SDimitry Andric }
10690b57cec5SDimitry Andric 
107004eeddc0SDimitry Andric /// If we have a global that is only initialized with a fixed size allocation
107104eeddc0SDimitry Andric /// try to transform the program to use global memory instead of heap
107204eeddc0SDimitry Andric /// allocated memory. This eliminates dynamic allocation, avoids an indirection
107304eeddc0SDimitry Andric /// accessing the data, and exposes the resultant global to further GlobalOpt.
107404eeddc0SDimitry Andric static bool tryToOptimizeStoreOfAllocationToGlobal(GlobalVariable *GV,
107504eeddc0SDimitry Andric                                                    CallInst *CI,
10760b57cec5SDimitry Andric                                                    const DataLayout &DL,
10770b57cec5SDimitry Andric                                                    TargetLibraryInfo *TLI) {
1078fcaf7f86SDimitry Andric   if (!isRemovableAlloc(CI, TLI))
107904eeddc0SDimitry Andric     // Must be able to remove the call when we get done..
108004eeddc0SDimitry Andric     return false;
108104eeddc0SDimitry Andric 
108204eeddc0SDimitry Andric   Type *Int8Ty = Type::getInt8Ty(CI->getFunction()->getContext());
108304eeddc0SDimitry Andric   Constant *InitVal = getInitialValueOfAllocation(CI, TLI, Int8Ty);
108404eeddc0SDimitry Andric   if (!InitVal)
108504eeddc0SDimitry Andric     // Must be able to emit a memset for initialization
108604eeddc0SDimitry Andric     return false;
108704eeddc0SDimitry Andric 
108804eeddc0SDimitry Andric   uint64_t AllocSize;
108904eeddc0SDimitry Andric   if (!getObjectSize(CI, AllocSize, DL, TLI, ObjectSizeOpts()))
109004eeddc0SDimitry Andric     return false;
109104eeddc0SDimitry Andric 
109204eeddc0SDimitry Andric   // Restrict this transformation to only working on small allocations
109304eeddc0SDimitry Andric   // (2048 bytes currently), as we don't want to introduce a 16M global or
109404eeddc0SDimitry Andric   // something.
109504eeddc0SDimitry Andric   if (AllocSize >= 2048)
10960b57cec5SDimitry Andric     return false;
10970b57cec5SDimitry Andric 
10980b57cec5SDimitry Andric   // We can't optimize this global unless all uses of it are *known* to be
10990b57cec5SDimitry Andric   // of the malloc value, not of the null initializer value (consider a use
11000b57cec5SDimitry Andric   // that compares the global's value against zero to see if the malloc has
11010b57cec5SDimitry Andric   // been reached).  To do this, we check to see if all uses of the global
11020b57cec5SDimitry Andric   // would trap if the global were null: this proves that they must all
11030b57cec5SDimitry Andric   // happen after the malloc.
1104349cc55cSDimitry Andric   if (!allUsesOfLoadedValueWillTrapIfNull(GV))
11050b57cec5SDimitry Andric     return false;
11060b57cec5SDimitry Andric 
11070b57cec5SDimitry Andric   // We can't optimize this if the malloc itself is used in a complex way,
11080b57cec5SDimitry Andric   // for example, being stored into multiple globals.  This allows the
1109349cc55cSDimitry Andric   // malloc to be stored into the specified global, loaded, gep, icmp'd.
1110fe6060f1SDimitry Andric   // These are all things we could transform to using the global for.
1111fe6060f1SDimitry Andric   if (!valueIsOnlyUsedLocallyOrStoredToOneGlobal(CI, GV))
11120b57cec5SDimitry Andric     return false;
11130b57cec5SDimitry Andric 
111404eeddc0SDimitry Andric   OptimizeGlobalAddressOfAllocation(GV, CI, AllocSize, InitVal, DL, TLI);
11150b57cec5SDimitry Andric   return true;
11160b57cec5SDimitry Andric }
11170b57cec5SDimitry Andric 
11180b57cec5SDimitry Andric // Try to optimize globals based on the knowledge that only one value (besides
11190b57cec5SDimitry Andric // its initializer) is ever stored to the global.
11208bcb0991SDimitry Andric static bool
11218bcb0991SDimitry Andric optimizeOnceStoredGlobal(GlobalVariable *GV, Value *StoredOnceVal,
112281ad6265SDimitry Andric                          const DataLayout &DL,
11238bcb0991SDimitry Andric                          function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
11240b57cec5SDimitry Andric   // Ignore no-op GEPs and bitcasts.
11250b57cec5SDimitry Andric   StoredOnceVal = StoredOnceVal->stripPointerCasts();
11260b57cec5SDimitry Andric 
11270b57cec5SDimitry Andric   // If we are dealing with a pointer global that is initialized to null and
11280b57cec5SDimitry Andric   // only has one (non-null) value stored into it, then we can optimize any
11290b57cec5SDimitry Andric   // users of the loaded value (often calls and loads) that would trap if the
11300b57cec5SDimitry Andric   // value was null.
11310b57cec5SDimitry Andric   if (GV->getInitializer()->getType()->isPointerTy() &&
11320b57cec5SDimitry Andric       GV->getInitializer()->isNullValue() &&
1133349cc55cSDimitry Andric       StoredOnceVal->getType()->isPointerTy() &&
11340b57cec5SDimitry Andric       !NullPointerIsDefined(
11350b57cec5SDimitry Andric           nullptr /* F */,
11360b57cec5SDimitry Andric           GV->getInitializer()->getType()->getPointerAddressSpace())) {
11370b57cec5SDimitry Andric     if (Constant *SOVC = dyn_cast<Constant>(StoredOnceVal)) {
11380b57cec5SDimitry Andric       // Optimize away any trapping uses of the loaded value.
11398bcb0991SDimitry Andric       if (OptimizeAwayTrappingUsesOfLoads(GV, SOVC, DL, GetTLI))
11400b57cec5SDimitry Andric         return true;
114104eeddc0SDimitry Andric     } else if (isAllocationFn(StoredOnceVal, GetTLI)) {
114204eeddc0SDimitry Andric       if (auto *CI = dyn_cast<CallInst>(StoredOnceVal)) {
11438bcb0991SDimitry Andric         auto *TLI = &GetTLI(*CI->getFunction());
114481ad6265SDimitry Andric         if (tryToOptimizeStoreOfAllocationToGlobal(GV, CI, DL, TLI))
11450b57cec5SDimitry Andric           return true;
11460b57cec5SDimitry Andric       }
11470b57cec5SDimitry Andric     }
114804eeddc0SDimitry Andric   }
11490b57cec5SDimitry Andric 
11500b57cec5SDimitry Andric   return false;
11510b57cec5SDimitry Andric }
11520b57cec5SDimitry Andric 
11530b57cec5SDimitry Andric /// At this point, we have learned that the only two values ever stored into GV
11540b57cec5SDimitry Andric /// are its initializer and OtherVal.  See if we can shrink the global into a
11550b57cec5SDimitry Andric /// boolean and select between the two values whenever it is used.  This exposes
11560b57cec5SDimitry Andric /// the values to other scalar optimizations.
11570b57cec5SDimitry Andric static bool TryToShrinkGlobalToBoolean(GlobalVariable *GV, Constant *OtherVal) {
11580b57cec5SDimitry Andric   Type *GVElType = GV->getValueType();
11590b57cec5SDimitry Andric 
11600b57cec5SDimitry Andric   // If GVElType is already i1, it is already shrunk.  If the type of the GV is
11610b57cec5SDimitry Andric   // an FP value, pointer or vector, don't do this optimization because a select
11620b57cec5SDimitry Andric   // between them is very expensive and unlikely to lead to later
11630b57cec5SDimitry Andric   // simplification.  In these cases, we typically end up with "cond ? v1 : v2"
11640b57cec5SDimitry Andric   // where v1 and v2 both require constant pool loads, a big loss.
11650b57cec5SDimitry Andric   if (GVElType == Type::getInt1Ty(GV->getContext()) ||
11660b57cec5SDimitry Andric       GVElType->isFloatingPointTy() ||
11670b57cec5SDimitry Andric       GVElType->isPointerTy() || GVElType->isVectorTy())
11680b57cec5SDimitry Andric     return false;
11690b57cec5SDimitry Andric 
11700b57cec5SDimitry Andric   // Walk the use list of the global seeing if all the uses are load or store.
11710b57cec5SDimitry Andric   // If there is anything else, bail out.
117204eeddc0SDimitry Andric   for (User *U : GV->users()) {
11730b57cec5SDimitry Andric     if (!isa<LoadInst>(U) && !isa<StoreInst>(U))
11740b57cec5SDimitry Andric       return false;
117504eeddc0SDimitry Andric     if (getLoadStoreType(U) != GVElType)
117604eeddc0SDimitry Andric       return false;
117704eeddc0SDimitry Andric   }
11780b57cec5SDimitry Andric 
11790b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "   *** SHRINKING TO BOOL: " << *GV << "\n");
11800b57cec5SDimitry Andric 
11810b57cec5SDimitry Andric   // Create the new global, initializing it to false.
11820b57cec5SDimitry Andric   GlobalVariable *NewGV = new GlobalVariable(Type::getInt1Ty(GV->getContext()),
11830b57cec5SDimitry Andric                                              false,
11840b57cec5SDimitry Andric                                              GlobalValue::InternalLinkage,
11850b57cec5SDimitry Andric                                         ConstantInt::getFalse(GV->getContext()),
11860b57cec5SDimitry Andric                                              GV->getName()+".b",
11870b57cec5SDimitry Andric                                              GV->getThreadLocalMode(),
11880b57cec5SDimitry Andric                                              GV->getType()->getAddressSpace());
11890b57cec5SDimitry Andric   NewGV->copyAttributesFrom(GV);
119006c3fb27SDimitry Andric   GV->getParent()->insertGlobalVariable(GV->getIterator(), NewGV);
11910b57cec5SDimitry Andric 
11920b57cec5SDimitry Andric   Constant *InitVal = GV->getInitializer();
11930b57cec5SDimitry Andric   assert(InitVal->getType() != Type::getInt1Ty(GV->getContext()) &&
11940b57cec5SDimitry Andric          "No reason to shrink to bool!");
11950b57cec5SDimitry Andric 
11960b57cec5SDimitry Andric   SmallVector<DIGlobalVariableExpression *, 1> GVs;
11970b57cec5SDimitry Andric   GV->getDebugInfo(GVs);
11980b57cec5SDimitry Andric 
11990b57cec5SDimitry Andric   // If initialized to zero and storing one into the global, we can use a cast
12000b57cec5SDimitry Andric   // instead of a select to synthesize the desired value.
12010b57cec5SDimitry Andric   bool IsOneZero = false;
12020b57cec5SDimitry Andric   bool EmitOneOrZero = true;
12038bcb0991SDimitry Andric   auto *CI = dyn_cast<ConstantInt>(OtherVal);
12048bcb0991SDimitry Andric   if (CI && CI->getValue().getActiveBits() <= 64) {
12050b57cec5SDimitry Andric     IsOneZero = InitVal->isNullValue() && CI->isOne();
12060b57cec5SDimitry Andric 
12078bcb0991SDimitry Andric     auto *CIInit = dyn_cast<ConstantInt>(GV->getInitializer());
12088bcb0991SDimitry Andric     if (CIInit && CIInit->getValue().getActiveBits() <= 64) {
12090b57cec5SDimitry Andric       uint64_t ValInit = CIInit->getZExtValue();
12100b57cec5SDimitry Andric       uint64_t ValOther = CI->getZExtValue();
12110b57cec5SDimitry Andric       uint64_t ValMinus = ValOther - ValInit;
12120b57cec5SDimitry Andric 
12130b57cec5SDimitry Andric       for(auto *GVe : GVs){
12140b57cec5SDimitry Andric         DIGlobalVariable *DGV = GVe->getVariable();
12150b57cec5SDimitry Andric         DIExpression *E = GVe->getExpression();
1216*0fca6ea1SDimitry Andric         const DataLayout &DL = GV->getDataLayout();
12170b57cec5SDimitry Andric         unsigned SizeInOctets =
1218fe6060f1SDimitry Andric             DL.getTypeAllocSizeInBits(NewGV->getValueType()) / 8;
12190b57cec5SDimitry Andric 
12200b57cec5SDimitry Andric         // It is expected that the address of global optimized variable is on
12210b57cec5SDimitry Andric         // top of the stack. After optimization, value of that variable will
12220b57cec5SDimitry Andric         // be ether 0 for initial value or 1 for other value. The following
12230b57cec5SDimitry Andric         // expression should return constant integer value depending on the
12240b57cec5SDimitry Andric         // value at global object address:
12250b57cec5SDimitry Andric         // val * (ValOther - ValInit) + ValInit:
12260b57cec5SDimitry Andric         // DW_OP_deref DW_OP_constu <ValMinus>
12270b57cec5SDimitry Andric         // DW_OP_mul DW_OP_constu <ValInit> DW_OP_plus DW_OP_stack_value
12280b57cec5SDimitry Andric         SmallVector<uint64_t, 12> Ops = {
12290b57cec5SDimitry Andric             dwarf::DW_OP_deref_size, SizeInOctets,
12300b57cec5SDimitry Andric             dwarf::DW_OP_constu, ValMinus,
12310b57cec5SDimitry Andric             dwarf::DW_OP_mul, dwarf::DW_OP_constu, ValInit,
12320b57cec5SDimitry Andric             dwarf::DW_OP_plus};
12330b57cec5SDimitry Andric         bool WithStackValue = true;
12340b57cec5SDimitry Andric         E = DIExpression::prependOpcodes(E, Ops, WithStackValue);
12350b57cec5SDimitry Andric         DIGlobalVariableExpression *DGVE =
12360b57cec5SDimitry Andric           DIGlobalVariableExpression::get(NewGV->getContext(), DGV, E);
12370b57cec5SDimitry Andric         NewGV->addDebugInfo(DGVE);
12380b57cec5SDimitry Andric      }
12390b57cec5SDimitry Andric      EmitOneOrZero = false;
12400b57cec5SDimitry Andric     }
12410b57cec5SDimitry Andric   }
12420b57cec5SDimitry Andric 
12430b57cec5SDimitry Andric   if (EmitOneOrZero) {
12440b57cec5SDimitry Andric      // FIXME: This will only emit address for debugger on which will
12450b57cec5SDimitry Andric      // be written only 0 or 1.
12460b57cec5SDimitry Andric      for(auto *GV : GVs)
12470b57cec5SDimitry Andric        NewGV->addDebugInfo(GV);
12480b57cec5SDimitry Andric    }
12490b57cec5SDimitry Andric 
12500b57cec5SDimitry Andric   while (!GV->use_empty()) {
12510b57cec5SDimitry Andric     Instruction *UI = cast<Instruction>(GV->user_back());
12520b57cec5SDimitry Andric     if (StoreInst *SI = dyn_cast<StoreInst>(UI)) {
12530b57cec5SDimitry Andric       // Change the store into a boolean store.
12540b57cec5SDimitry Andric       bool StoringOther = SI->getOperand(0) == OtherVal;
12550b57cec5SDimitry Andric       // Only do this if we weren't storing a loaded value.
12560b57cec5SDimitry Andric       Value *StoreVal;
12570b57cec5SDimitry Andric       if (StoringOther || SI->getOperand(0) == InitVal) {
12580b57cec5SDimitry Andric         StoreVal = ConstantInt::get(Type::getInt1Ty(GV->getContext()),
12590b57cec5SDimitry Andric                                     StoringOther);
12600b57cec5SDimitry Andric       } else {
12610b57cec5SDimitry Andric         // Otherwise, we are storing a previously loaded copy.  To do this,
12620b57cec5SDimitry Andric         // change the copy from copying the original value to just copying the
12630b57cec5SDimitry Andric         // bool.
12640b57cec5SDimitry Andric         Instruction *StoredVal = cast<Instruction>(SI->getOperand(0));
12650b57cec5SDimitry Andric 
12660b57cec5SDimitry Andric         // If we've already replaced the input, StoredVal will be a cast or
12670b57cec5SDimitry Andric         // select instruction.  If not, it will be a load of the original
12680b57cec5SDimitry Andric         // global.
12690b57cec5SDimitry Andric         if (LoadInst *LI = dyn_cast<LoadInst>(StoredVal)) {
12700b57cec5SDimitry Andric           assert(LI->getOperand(0) == GV && "Not a copy!");
12710b57cec5SDimitry Andric           // Insert a new load, to preserve the saved value.
1272*0fca6ea1SDimitry Andric           StoreVal =
1273*0fca6ea1SDimitry Andric               new LoadInst(NewGV->getValueType(), NewGV, LI->getName() + ".b",
1274*0fca6ea1SDimitry Andric                            false, Align(1), LI->getOrdering(),
1275*0fca6ea1SDimitry Andric                            LI->getSyncScopeID(), LI->getIterator());
12760b57cec5SDimitry Andric         } else {
12770b57cec5SDimitry Andric           assert((isa<CastInst>(StoredVal) || isa<SelectInst>(StoredVal)) &&
12780b57cec5SDimitry Andric                  "This is not a form that we understand!");
12790b57cec5SDimitry Andric           StoreVal = StoredVal->getOperand(0);
12800b57cec5SDimitry Andric           assert(isa<LoadInst>(StoreVal) && "Not a load of NewGV!");
12810b57cec5SDimitry Andric         }
12820b57cec5SDimitry Andric       }
12830b57cec5SDimitry Andric       StoreInst *NSI =
12845ffd83dbSDimitry Andric           new StoreInst(StoreVal, NewGV, false, Align(1), SI->getOrdering(),
1285*0fca6ea1SDimitry Andric                         SI->getSyncScopeID(), SI->getIterator());
12860b57cec5SDimitry Andric       NSI->setDebugLoc(SI->getDebugLoc());
12870b57cec5SDimitry Andric     } else {
12880b57cec5SDimitry Andric       // Change the load into a load of bool then a select.
12890b57cec5SDimitry Andric       LoadInst *LI = cast<LoadInst>(UI);
1290*0fca6ea1SDimitry Andric       LoadInst *NLI = new LoadInst(
1291*0fca6ea1SDimitry Andric           NewGV->getValueType(), NewGV, LI->getName() + ".b", false, Align(1),
1292*0fca6ea1SDimitry Andric           LI->getOrdering(), LI->getSyncScopeID(), LI->getIterator());
12930b57cec5SDimitry Andric       Instruction *NSI;
12940b57cec5SDimitry Andric       if (IsOneZero)
1295*0fca6ea1SDimitry Andric         NSI = new ZExtInst(NLI, LI->getType(), "", LI->getIterator());
12960b57cec5SDimitry Andric       else
1297*0fca6ea1SDimitry Andric         NSI = SelectInst::Create(NLI, OtherVal, InitVal, "", LI->getIterator());
12980b57cec5SDimitry Andric       NSI->takeName(LI);
12990b57cec5SDimitry Andric       // Since LI is split into two instructions, NLI and NSI both inherit the
13000b57cec5SDimitry Andric       // same DebugLoc
13010b57cec5SDimitry Andric       NLI->setDebugLoc(LI->getDebugLoc());
13020b57cec5SDimitry Andric       NSI->setDebugLoc(LI->getDebugLoc());
13030b57cec5SDimitry Andric       LI->replaceAllUsesWith(NSI);
13040b57cec5SDimitry Andric     }
13050b57cec5SDimitry Andric     UI->eraseFromParent();
13060b57cec5SDimitry Andric   }
13070b57cec5SDimitry Andric 
13080b57cec5SDimitry Andric   // Retain the name of the old global variable. People who are debugging their
13090b57cec5SDimitry Andric   // programs may expect these variables to be named the same.
13100b57cec5SDimitry Andric   NewGV->takeName(GV);
13110b57cec5SDimitry Andric   GV->eraseFromParent();
13120b57cec5SDimitry Andric   return true;
13130b57cec5SDimitry Andric }
13140b57cec5SDimitry Andric 
131581ad6265SDimitry Andric static bool
131681ad6265SDimitry Andric deleteIfDead(GlobalValue &GV,
131781ad6265SDimitry Andric              SmallPtrSetImpl<const Comdat *> &NotDiscardableComdats,
131881ad6265SDimitry Andric              function_ref<void(Function &)> DeleteFnCallback = nullptr) {
13190b57cec5SDimitry Andric   GV.removeDeadConstantUsers();
13200b57cec5SDimitry Andric 
13210b57cec5SDimitry Andric   if (!GV.isDiscardableIfUnused() && !GV.isDeclaration())
13220b57cec5SDimitry Andric     return false;
13230b57cec5SDimitry Andric 
13240b57cec5SDimitry Andric   if (const Comdat *C = GV.getComdat())
13250b57cec5SDimitry Andric     if (!GV.hasLocalLinkage() && NotDiscardableComdats.count(C))
13260b57cec5SDimitry Andric       return false;
13270b57cec5SDimitry Andric 
13280b57cec5SDimitry Andric   bool Dead;
13290b57cec5SDimitry Andric   if (auto *F = dyn_cast<Function>(&GV))
13300b57cec5SDimitry Andric     Dead = (F->isDeclaration() && F->use_empty()) || F->isDefTriviallyDead();
13310b57cec5SDimitry Andric   else
13320b57cec5SDimitry Andric     Dead = GV.use_empty();
13330b57cec5SDimitry Andric   if (!Dead)
13340b57cec5SDimitry Andric     return false;
13350b57cec5SDimitry Andric 
13360b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "GLOBAL DEAD: " << GV << "\n");
133781ad6265SDimitry Andric   if (auto *F = dyn_cast<Function>(&GV)) {
133881ad6265SDimitry Andric     if (DeleteFnCallback)
133981ad6265SDimitry Andric       DeleteFnCallback(*F);
134081ad6265SDimitry Andric   }
13410b57cec5SDimitry Andric   GV.eraseFromParent();
13420b57cec5SDimitry Andric   ++NumDeleted;
13430b57cec5SDimitry Andric   return true;
13440b57cec5SDimitry Andric }
13450b57cec5SDimitry Andric 
13460b57cec5SDimitry Andric static bool isPointerValueDeadOnEntryToFunction(
13470b57cec5SDimitry Andric     const Function *F, GlobalValue *GV,
13480b57cec5SDimitry Andric     function_ref<DominatorTree &(Function &)> LookupDomTree) {
13490b57cec5SDimitry Andric   // Find all uses of GV. We expect them all to be in F, and if we can't
13500b57cec5SDimitry Andric   // identify any of the uses we bail out.
13510b57cec5SDimitry Andric   //
13520b57cec5SDimitry Andric   // On each of these uses, identify if the memory that GV points to is
13530b57cec5SDimitry Andric   // used/required/live at the start of the function. If it is not, for example
13540b57cec5SDimitry Andric   // if the first thing the function does is store to the GV, the GV can
13550b57cec5SDimitry Andric   // possibly be demoted.
13560b57cec5SDimitry Andric   //
13570b57cec5SDimitry Andric   // We don't do an exhaustive search for memory operations - simply look
13580b57cec5SDimitry Andric   // through bitcasts as they're quite common and benign.
1359*0fca6ea1SDimitry Andric   const DataLayout &DL = GV->getDataLayout();
13600b57cec5SDimitry Andric   SmallVector<LoadInst *, 4> Loads;
13610b57cec5SDimitry Andric   SmallVector<StoreInst *, 4> Stores;
13620b57cec5SDimitry Andric   for (auto *U : GV->users()) {
13630b57cec5SDimitry Andric     Instruction *I = dyn_cast<Instruction>(U);
13640b57cec5SDimitry Andric     if (!I)
13650b57cec5SDimitry Andric       return false;
13660b57cec5SDimitry Andric     assert(I->getParent()->getParent() == F);
13670b57cec5SDimitry Andric 
13680b57cec5SDimitry Andric     if (auto *LI = dyn_cast<LoadInst>(I))
13690b57cec5SDimitry Andric       Loads.push_back(LI);
13700b57cec5SDimitry Andric     else if (auto *SI = dyn_cast<StoreInst>(I))
13710b57cec5SDimitry Andric       Stores.push_back(SI);
13720b57cec5SDimitry Andric     else
13730b57cec5SDimitry Andric       return false;
13740b57cec5SDimitry Andric   }
13750b57cec5SDimitry Andric 
13760b57cec5SDimitry Andric   // We have identified all uses of GV into loads and stores. Now check if all
13770b57cec5SDimitry Andric   // of them are known not to depend on the value of the global at the function
13780b57cec5SDimitry Andric   // entry point. We do this by ensuring that every load is dominated by at
13790b57cec5SDimitry Andric   // least one store.
13800b57cec5SDimitry Andric   auto &DT = LookupDomTree(*const_cast<Function *>(F));
13810b57cec5SDimitry Andric 
13820b57cec5SDimitry Andric   // The below check is quadratic. Check we're not going to do too many tests.
13830b57cec5SDimitry Andric   // FIXME: Even though this will always have worst-case quadratic time, we
13840b57cec5SDimitry Andric   // could put effort into minimizing the average time by putting stores that
13850b57cec5SDimitry Andric   // have been shown to dominate at least one load at the beginning of the
13860b57cec5SDimitry Andric   // Stores array, making subsequent dominance checks more likely to succeed
13870b57cec5SDimitry Andric   // early.
13880b57cec5SDimitry Andric   //
13890b57cec5SDimitry Andric   // The threshold here is fairly large because global->local demotion is a
13900b57cec5SDimitry Andric   // very powerful optimization should it fire.
13910b57cec5SDimitry Andric   const unsigned Threshold = 100;
13920b57cec5SDimitry Andric   if (Loads.size() * Stores.size() > Threshold)
13930b57cec5SDimitry Andric     return false;
13940b57cec5SDimitry Andric 
13950b57cec5SDimitry Andric   for (auto *L : Loads) {
13960b57cec5SDimitry Andric     auto *LTy = L->getType();
13970b57cec5SDimitry Andric     if (none_of(Stores, [&](const StoreInst *S) {
13980b57cec5SDimitry Andric           auto *STy = S->getValueOperand()->getType();
13990b57cec5SDimitry Andric           // The load is only dominated by the store if DomTree says so
14000b57cec5SDimitry Andric           // and the number of bits loaded in L is less than or equal to
14010b57cec5SDimitry Andric           // the number of bits stored in S.
14020b57cec5SDimitry Andric           return DT.dominates(S, L) &&
1403bdd1243dSDimitry Andric                  DL.getTypeStoreSize(LTy).getFixedValue() <=
1404bdd1243dSDimitry Andric                      DL.getTypeStoreSize(STy).getFixedValue();
14050b57cec5SDimitry Andric         }))
14060b57cec5SDimitry Andric       return false;
14070b57cec5SDimitry Andric   }
14080b57cec5SDimitry Andric   // All loads have known dependences inside F, so the global can be localized.
14090b57cec5SDimitry Andric   return true;
14100b57cec5SDimitry Andric }
14110b57cec5SDimitry Andric 
141281ad6265SDimitry Andric // For a global variable with one store, if the store dominates any loads,
141381ad6265SDimitry Andric // those loads will always load the stored value (as opposed to the
141481ad6265SDimitry Andric // initializer), even in the presence of recursion.
141581ad6265SDimitry Andric static bool forwardStoredOnceStore(
141681ad6265SDimitry Andric     GlobalVariable *GV, const StoreInst *StoredOnceStore,
141781ad6265SDimitry Andric     function_ref<DominatorTree &(Function &)> LookupDomTree) {
141881ad6265SDimitry Andric   const Value *StoredOnceValue = StoredOnceStore->getValueOperand();
141981ad6265SDimitry Andric   // We can do this optimization for non-constants in nosync + norecurse
142081ad6265SDimitry Andric   // functions, but globals used in exactly one norecurse functions are already
142181ad6265SDimitry Andric   // promoted to an alloca.
142281ad6265SDimitry Andric   if (!isa<Constant>(StoredOnceValue))
142381ad6265SDimitry Andric     return false;
142481ad6265SDimitry Andric   const Function *F = StoredOnceStore->getFunction();
142581ad6265SDimitry Andric   SmallVector<LoadInst *> Loads;
142681ad6265SDimitry Andric   for (User *U : GV->users()) {
142781ad6265SDimitry Andric     if (auto *LI = dyn_cast<LoadInst>(U)) {
142881ad6265SDimitry Andric       if (LI->getFunction() == F &&
142981ad6265SDimitry Andric           LI->getType() == StoredOnceValue->getType() && LI->isSimple())
143081ad6265SDimitry Andric         Loads.push_back(LI);
143181ad6265SDimitry Andric     }
143281ad6265SDimitry Andric   }
143381ad6265SDimitry Andric   // Only compute DT if we have any loads to examine.
143481ad6265SDimitry Andric   bool MadeChange = false;
143581ad6265SDimitry Andric   if (!Loads.empty()) {
143681ad6265SDimitry Andric     auto &DT = LookupDomTree(*const_cast<Function *>(F));
143781ad6265SDimitry Andric     for (auto *LI : Loads) {
143881ad6265SDimitry Andric       if (DT.dominates(StoredOnceStore, LI)) {
143981ad6265SDimitry Andric         LI->replaceAllUsesWith(const_cast<Value *>(StoredOnceValue));
144081ad6265SDimitry Andric         LI->eraseFromParent();
144181ad6265SDimitry Andric         MadeChange = true;
144281ad6265SDimitry Andric       }
144381ad6265SDimitry Andric     }
144481ad6265SDimitry Andric   }
144581ad6265SDimitry Andric   return MadeChange;
144681ad6265SDimitry Andric }
144781ad6265SDimitry Andric 
14480b57cec5SDimitry Andric /// Analyze the specified global variable and optimize
14490b57cec5SDimitry Andric /// it if possible.  If we make a change, return true.
14508bcb0991SDimitry Andric static bool
14518bcb0991SDimitry Andric processInternalGlobal(GlobalVariable *GV, const GlobalStatus &GS,
1452349cc55cSDimitry Andric                       function_ref<TargetTransformInfo &(Function &)> GetTTI,
14538bcb0991SDimitry Andric                       function_ref<TargetLibraryInfo &(Function &)> GetTLI,
14540b57cec5SDimitry Andric                       function_ref<DominatorTree &(Function &)> LookupDomTree) {
1455*0fca6ea1SDimitry Andric   auto &DL = GV->getDataLayout();
14560b57cec5SDimitry Andric   // If this is a first class global and has only one accessing function and
14570b57cec5SDimitry Andric   // this function is non-recursive, we replace the global with a local alloca
14580b57cec5SDimitry Andric   // in this function.
14590b57cec5SDimitry Andric   //
14600b57cec5SDimitry Andric   // NOTE: It doesn't make sense to promote non-single-value types since we
14610b57cec5SDimitry Andric   // are just replacing static memory to stack memory.
14620b57cec5SDimitry Andric   //
14630b57cec5SDimitry Andric   // If the global is in different address space, don't bring it to stack.
14640b57cec5SDimitry Andric   if (!GS.HasMultipleAccessingFunctions &&
14650b57cec5SDimitry Andric       GS.AccessingFunction &&
14660b57cec5SDimitry Andric       GV->getValueType()->isSingleValueType() &&
14675f757f3fSDimitry Andric       GV->getType()->getAddressSpace() == DL.getAllocaAddrSpace() &&
14680b57cec5SDimitry Andric       !GV->isExternallyInitialized() &&
14690b57cec5SDimitry Andric       GS.AccessingFunction->doesNotRecurse() &&
14700b57cec5SDimitry Andric       isPointerValueDeadOnEntryToFunction(GS.AccessingFunction, GV,
14710b57cec5SDimitry Andric                                           LookupDomTree)) {
1472*0fca6ea1SDimitry Andric     const DataLayout &DL = GV->getDataLayout();
14730b57cec5SDimitry Andric 
14740b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "LOCALIZING GLOBAL: " << *GV << "\n");
1475*0fca6ea1SDimitry Andric     BasicBlock::iterator FirstI =
1476*0fca6ea1SDimitry Andric         GS.AccessingFunction->getEntryBlock().begin().getNonConst();
14770b57cec5SDimitry Andric     Type *ElemTy = GV->getValueType();
14780b57cec5SDimitry Andric     // FIXME: Pass Global's alignment when globals have alignment
1479*0fca6ea1SDimitry Andric     AllocaInst *Alloca = new AllocaInst(ElemTy, DL.getAllocaAddrSpace(),
1480*0fca6ea1SDimitry Andric                                         nullptr, GV->getName(), FirstI);
14810b57cec5SDimitry Andric     if (!isa<UndefValue>(GV->getInitializer()))
1482*0fca6ea1SDimitry Andric       new StoreInst(GV->getInitializer(), Alloca, FirstI);
14830b57cec5SDimitry Andric 
14840b57cec5SDimitry Andric     GV->replaceAllUsesWith(Alloca);
14850b57cec5SDimitry Andric     GV->eraseFromParent();
14860b57cec5SDimitry Andric     ++NumLocalized;
14870b57cec5SDimitry Andric     return true;
14880b57cec5SDimitry Andric   }
14890b57cec5SDimitry Andric 
1490e8d8bef9SDimitry Andric   bool Changed = false;
1491e8d8bef9SDimitry Andric 
14920b57cec5SDimitry Andric   // If the global is never loaded (but may be stored to), it is dead.
14930b57cec5SDimitry Andric   // Delete it now.
14940b57cec5SDimitry Andric   if (!GS.IsLoaded) {
14950b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "GLOBAL NEVER LOADED: " << *GV << "\n");
14960b57cec5SDimitry Andric 
14970b57cec5SDimitry Andric     if (isLeakCheckerRoot(GV)) {
14980b57cec5SDimitry Andric       // Delete any constant stores to the global.
14998bcb0991SDimitry Andric       Changed = CleanupPointerRootUsers(GV, GetTLI);
15000b57cec5SDimitry Andric     } else {
15010b57cec5SDimitry Andric       // Delete any stores we can find to the global.  We may not be able to
15020b57cec5SDimitry Andric       // make it completely dead though.
15034824e7fdSDimitry Andric       Changed = CleanupConstantGlobalUsers(GV, DL);
15040b57cec5SDimitry Andric     }
15050b57cec5SDimitry Andric 
15060b57cec5SDimitry Andric     // If the global is dead now, delete it.
15070b57cec5SDimitry Andric     if (GV->use_empty()) {
15080b57cec5SDimitry Andric       GV->eraseFromParent();
15090b57cec5SDimitry Andric       ++NumDeleted;
15100b57cec5SDimitry Andric       Changed = true;
15110b57cec5SDimitry Andric     }
15120b57cec5SDimitry Andric     return Changed;
15130b57cec5SDimitry Andric 
15140b57cec5SDimitry Andric   }
15150b57cec5SDimitry Andric   if (GS.StoredType <= GlobalStatus::InitializerStored) {
15160b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "MARKING CONSTANT: " << *GV << "\n");
15170b57cec5SDimitry Andric 
15180b57cec5SDimitry Andric     // Don't actually mark a global constant if it's atomic because atomic loads
15190b57cec5SDimitry Andric     // are implemented by a trivial cmpxchg in some edge-cases and that usually
15200b57cec5SDimitry Andric     // requires write access to the variable even if it's not actually changed.
1521e8d8bef9SDimitry Andric     if (GS.Ordering == AtomicOrdering::NotAtomic) {
1522e8d8bef9SDimitry Andric       assert(!GV->isConstant() && "Expected a non-constant global");
15230b57cec5SDimitry Andric       GV->setConstant(true);
1524e8d8bef9SDimitry Andric       Changed = true;
1525e8d8bef9SDimitry Andric     }
15260b57cec5SDimitry Andric 
15270b57cec5SDimitry Andric     // Clean up any obviously simplifiable users now.
15284824e7fdSDimitry Andric     Changed |= CleanupConstantGlobalUsers(GV, DL);
15290b57cec5SDimitry Andric 
15300b57cec5SDimitry Andric     // If the global is dead now, just nuke it.
15310b57cec5SDimitry Andric     if (GV->use_empty()) {
15320b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "   *** Marking constant allowed us to simplify "
15330b57cec5SDimitry Andric                         << "all users and delete global!\n");
15340b57cec5SDimitry Andric       GV->eraseFromParent();
15350b57cec5SDimitry Andric       ++NumDeleted;
15360b57cec5SDimitry Andric       return true;
15370b57cec5SDimitry Andric     }
15380b57cec5SDimitry Andric 
15390b57cec5SDimitry Andric     // Fall through to the next check; see if we can optimize further.
15400b57cec5SDimitry Andric     ++NumMarked;
15410b57cec5SDimitry Andric   }
15420b57cec5SDimitry Andric   if (!GV->getInitializer()->getType()->isSingleValueType()) {
1543*0fca6ea1SDimitry Andric     const DataLayout &DL = GV->getDataLayout();
15440b57cec5SDimitry Andric     if (SRAGlobal(GV, DL))
15450b57cec5SDimitry Andric       return true;
15460b57cec5SDimitry Andric   }
1547349cc55cSDimitry Andric   Value *StoredOnceValue = GS.getStoredOnceValue();
1548349cc55cSDimitry Andric   if (GS.StoredType == GlobalStatus::StoredOnce && StoredOnceValue) {
1549349cc55cSDimitry Andric     Function &StoreFn =
1550349cc55cSDimitry Andric         const_cast<Function &>(*GS.StoredOnceStore->getFunction());
1551349cc55cSDimitry Andric     bool CanHaveNonUndefGlobalInitializer =
1552349cc55cSDimitry Andric         GetTTI(StoreFn).canHaveNonUndefGlobalInitializerInAddressSpace(
1553349cc55cSDimitry Andric             GV->getType()->getAddressSpace());
15540b57cec5SDimitry Andric     // If the initial value for the global was an undef value, and if only
15550b57cec5SDimitry Andric     // one other value was stored into it, we can just change the
15560b57cec5SDimitry Andric     // initializer to be the stored value, then delete all stores to the
15570b57cec5SDimitry Andric     // global.  This allows us to mark it constant.
1558349cc55cSDimitry Andric     // This is restricted to address spaces that allow globals to have
1559349cc55cSDimitry Andric     // initializers. NVPTX, for example, does not support initializers for
1560349cc55cSDimitry Andric     // shared memory (AS 3).
1561753f127fSDimitry Andric     auto *SOVConstant = dyn_cast<Constant>(StoredOnceValue);
156204eeddc0SDimitry Andric     if (SOVConstant && isa<UndefValue>(GV->getInitializer()) &&
156304eeddc0SDimitry Andric         DL.getTypeAllocSize(SOVConstant->getType()) ==
156404eeddc0SDimitry Andric             DL.getTypeAllocSize(GV->getValueType()) &&
1565349cc55cSDimitry Andric         CanHaveNonUndefGlobalInitializer) {
156604eeddc0SDimitry Andric       if (SOVConstant->getType() == GV->getValueType()) {
156704eeddc0SDimitry Andric         // Change the initializer in place.
15680b57cec5SDimitry Andric         GV->setInitializer(SOVConstant);
156904eeddc0SDimitry Andric       } else {
157004eeddc0SDimitry Andric         // Create a new global with adjusted type.
157104eeddc0SDimitry Andric         auto *NGV = new GlobalVariable(
157204eeddc0SDimitry Andric             *GV->getParent(), SOVConstant->getType(), GV->isConstant(),
157304eeddc0SDimitry Andric             GV->getLinkage(), SOVConstant, "", GV, GV->getThreadLocalMode(),
157404eeddc0SDimitry Andric             GV->getAddressSpace());
157504eeddc0SDimitry Andric         NGV->takeName(GV);
157604eeddc0SDimitry Andric         NGV->copyAttributesFrom(GV);
15775f757f3fSDimitry Andric         GV->replaceAllUsesWith(NGV);
157804eeddc0SDimitry Andric         GV->eraseFromParent();
157904eeddc0SDimitry Andric         GV = NGV;
158004eeddc0SDimitry Andric       }
15810b57cec5SDimitry Andric 
15820b57cec5SDimitry Andric       // Clean up any obviously simplifiable users now.
15834824e7fdSDimitry Andric       CleanupConstantGlobalUsers(GV, DL);
15840b57cec5SDimitry Andric 
15850b57cec5SDimitry Andric       if (GV->use_empty()) {
15860b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "   *** Substituting initializer allowed us to "
15870b57cec5SDimitry Andric                           << "simplify all users and delete global!\n");
15880b57cec5SDimitry Andric         GV->eraseFromParent();
15890b57cec5SDimitry Andric         ++NumDeleted;
15900b57cec5SDimitry Andric       }
15910b57cec5SDimitry Andric       ++NumSubstitute;
15920b57cec5SDimitry Andric       return true;
15930b57cec5SDimitry Andric     }
15940b57cec5SDimitry Andric 
15950b57cec5SDimitry Andric     // Try to optimize globals based on the knowledge that only one value
15960b57cec5SDimitry Andric     // (besides its initializer) is ever stored to the global.
159781ad6265SDimitry Andric     if (optimizeOnceStoredGlobal(GV, StoredOnceValue, DL, GetTLI))
159881ad6265SDimitry Andric       return true;
159981ad6265SDimitry Andric 
160081ad6265SDimitry Andric     // Try to forward the store to any loads. If we have more than one store, we
160181ad6265SDimitry Andric     // may have a store of the initializer between StoredOnceStore and a load.
160281ad6265SDimitry Andric     if (GS.NumStores == 1)
160381ad6265SDimitry Andric       if (forwardStoredOnceStore(GV, GS.StoredOnceStore, LookupDomTree))
16040b57cec5SDimitry Andric         return true;
16050b57cec5SDimitry Andric 
16060b57cec5SDimitry Andric     // Otherwise, if the global was not a boolean, we can shrink it to be a
1607349cc55cSDimitry Andric     // boolean. Skip this optimization for AS that doesn't allow an initializer.
1608349cc55cSDimitry Andric     if (SOVConstant && GS.Ordering == AtomicOrdering::NotAtomic &&
1609349cc55cSDimitry Andric         (!isa<UndefValue>(GV->getInitializer()) ||
1610349cc55cSDimitry Andric          CanHaveNonUndefGlobalInitializer)) {
16110b57cec5SDimitry Andric       if (TryToShrinkGlobalToBoolean(GV, SOVConstant)) {
16120b57cec5SDimitry Andric         ++NumShrunkToBool;
16130b57cec5SDimitry Andric         return true;
16140b57cec5SDimitry Andric       }
16150b57cec5SDimitry Andric     }
16160b57cec5SDimitry Andric   }
16170b57cec5SDimitry Andric 
1618e8d8bef9SDimitry Andric   return Changed;
16190b57cec5SDimitry Andric }
16200b57cec5SDimitry Andric 
16210b57cec5SDimitry Andric /// Analyze the specified global variable and optimize it if possible.  If we
16220b57cec5SDimitry Andric /// make a change, return true.
16230b57cec5SDimitry Andric static bool
16248bcb0991SDimitry Andric processGlobal(GlobalValue &GV,
1625349cc55cSDimitry Andric               function_ref<TargetTransformInfo &(Function &)> GetTTI,
16268bcb0991SDimitry Andric               function_ref<TargetLibraryInfo &(Function &)> GetTLI,
16270b57cec5SDimitry Andric               function_ref<DominatorTree &(Function &)> LookupDomTree) {
16285f757f3fSDimitry Andric   if (GV.getName().starts_with("llvm."))
16290b57cec5SDimitry Andric     return false;
16300b57cec5SDimitry Andric 
16310b57cec5SDimitry Andric   GlobalStatus GS;
16320b57cec5SDimitry Andric 
16330b57cec5SDimitry Andric   if (GlobalStatus::analyzeGlobal(&GV, GS))
16340b57cec5SDimitry Andric     return false;
16350b57cec5SDimitry Andric 
16360b57cec5SDimitry Andric   bool Changed = false;
16370b57cec5SDimitry Andric   if (!GS.IsCompared && !GV.hasGlobalUnnamedAddr()) {
16380b57cec5SDimitry Andric     auto NewUnnamedAddr = GV.hasLocalLinkage() ? GlobalValue::UnnamedAddr::Global
16390b57cec5SDimitry Andric                                                : GlobalValue::UnnamedAddr::Local;
16400b57cec5SDimitry Andric     if (NewUnnamedAddr != GV.getUnnamedAddr()) {
16410b57cec5SDimitry Andric       GV.setUnnamedAddr(NewUnnamedAddr);
16420b57cec5SDimitry Andric       NumUnnamed++;
16430b57cec5SDimitry Andric       Changed = true;
16440b57cec5SDimitry Andric     }
16450b57cec5SDimitry Andric   }
16460b57cec5SDimitry Andric 
16470b57cec5SDimitry Andric   // Do more involved optimizations if the global is internal.
16480b57cec5SDimitry Andric   if (!GV.hasLocalLinkage())
16490b57cec5SDimitry Andric     return Changed;
16500b57cec5SDimitry Andric 
16510b57cec5SDimitry Andric   auto *GVar = dyn_cast<GlobalVariable>(&GV);
16520b57cec5SDimitry Andric   if (!GVar)
16530b57cec5SDimitry Andric     return Changed;
16540b57cec5SDimitry Andric 
16550b57cec5SDimitry Andric   if (GVar->isConstant() || !GVar->hasInitializer())
16560b57cec5SDimitry Andric     return Changed;
16570b57cec5SDimitry Andric 
1658349cc55cSDimitry Andric   return processInternalGlobal(GVar, GS, GetTTI, GetTLI, LookupDomTree) ||
1659349cc55cSDimitry Andric          Changed;
16600b57cec5SDimitry Andric }
16610b57cec5SDimitry Andric 
16620b57cec5SDimitry Andric /// Walk all of the direct calls of the specified function, changing them to
16630b57cec5SDimitry Andric /// FastCC.
16640b57cec5SDimitry Andric static void ChangeCalleesToFastCall(Function *F) {
16650b57cec5SDimitry Andric   for (User *U : F->users()) {
16660b57cec5SDimitry Andric     if (isa<BlockAddress>(U))
16670b57cec5SDimitry Andric       continue;
16685ffd83dbSDimitry Andric     cast<CallBase>(U)->setCallingConv(CallingConv::Fast);
16690b57cec5SDimitry Andric   }
16700b57cec5SDimitry Andric }
16710b57cec5SDimitry Andric 
16720b57cec5SDimitry Andric static AttributeList StripAttr(LLVMContext &C, AttributeList Attrs,
16730b57cec5SDimitry Andric                                Attribute::AttrKind A) {
16740b57cec5SDimitry Andric   unsigned AttrIndex;
16750b57cec5SDimitry Andric   if (Attrs.hasAttrSomewhere(A, &AttrIndex))
1676349cc55cSDimitry Andric     return Attrs.removeAttributeAtIndex(C, AttrIndex, A);
16770b57cec5SDimitry Andric   return Attrs;
16780b57cec5SDimitry Andric }
16790b57cec5SDimitry Andric 
16800b57cec5SDimitry Andric static void RemoveAttribute(Function *F, Attribute::AttrKind A) {
16810b57cec5SDimitry Andric   F->setAttributes(StripAttr(F->getContext(), F->getAttributes(), A));
16820b57cec5SDimitry Andric   for (User *U : F->users()) {
16830b57cec5SDimitry Andric     if (isa<BlockAddress>(U))
16840b57cec5SDimitry Andric       continue;
16855ffd83dbSDimitry Andric     CallBase *CB = cast<CallBase>(U);
16865ffd83dbSDimitry Andric     CB->setAttributes(StripAttr(F->getContext(), CB->getAttributes(), A));
16870b57cec5SDimitry Andric   }
16880b57cec5SDimitry Andric }
16890b57cec5SDimitry Andric 
16900b57cec5SDimitry Andric /// Return true if this is a calling convention that we'd like to change.  The
16910b57cec5SDimitry Andric /// idea here is that we don't want to mess with the convention if the user
16920b57cec5SDimitry Andric /// explicitly requested something with performance implications like coldcc,
16930b57cec5SDimitry Andric /// GHC, or anyregcc.
1694b121cb00SDimitry Andric static bool hasChangeableCCImpl(Function *F) {
16950b57cec5SDimitry Andric   CallingConv::ID CC = F->getCallingConv();
16960b57cec5SDimitry Andric 
16970b57cec5SDimitry Andric   // FIXME: Is it worth transforming x86_stdcallcc and x86_fastcallcc?
16980b57cec5SDimitry Andric   if (CC != CallingConv::C && CC != CallingConv::X86_ThisCall)
16990b57cec5SDimitry Andric     return false;
17000b57cec5SDimitry Andric 
1701b121cb00SDimitry Andric   if (F->isVarArg())
1702b121cb00SDimitry Andric     return false;
1703b121cb00SDimitry Andric 
17040b57cec5SDimitry Andric   // FIXME: Change CC for the whole chain of musttail calls when possible.
17050b57cec5SDimitry Andric   //
17060b57cec5SDimitry Andric   // Can't change CC of the function that either has musttail calls, or is a
17070b57cec5SDimitry Andric   // musttail callee itself
17080b57cec5SDimitry Andric   for (User *U : F->users()) {
17090b57cec5SDimitry Andric     if (isa<BlockAddress>(U))
17100b57cec5SDimitry Andric       continue;
17110b57cec5SDimitry Andric     CallInst* CI = dyn_cast<CallInst>(U);
17120b57cec5SDimitry Andric     if (!CI)
17130b57cec5SDimitry Andric       continue;
17140b57cec5SDimitry Andric 
17150b57cec5SDimitry Andric     if (CI->isMustTailCall())
17160b57cec5SDimitry Andric       return false;
17170b57cec5SDimitry Andric   }
17180b57cec5SDimitry Andric 
17190b57cec5SDimitry Andric   for (BasicBlock &BB : *F)
17200b57cec5SDimitry Andric     if (BB.getTerminatingMustTailCall())
17210b57cec5SDimitry Andric       return false;
17220b57cec5SDimitry Andric 
1723b121cb00SDimitry Andric   return !F->hasAddressTaken();
1724b121cb00SDimitry Andric }
1725b121cb00SDimitry Andric 
1726b121cb00SDimitry Andric using ChangeableCCCacheTy = SmallDenseMap<Function *, bool, 8>;
1727b121cb00SDimitry Andric static bool hasChangeableCC(Function *F,
1728b121cb00SDimitry Andric                             ChangeableCCCacheTy &ChangeableCCCache) {
1729b121cb00SDimitry Andric   auto Res = ChangeableCCCache.try_emplace(F, false);
1730b121cb00SDimitry Andric   if (Res.second)
1731b121cb00SDimitry Andric     Res.first->second = hasChangeableCCImpl(F);
1732b121cb00SDimitry Andric   return Res.first->second;
17330b57cec5SDimitry Andric }
17340b57cec5SDimitry Andric 
17350b57cec5SDimitry Andric /// Return true if the block containing the call site has a BlockFrequency of
17360b57cec5SDimitry Andric /// less than ColdCCRelFreq% of the entry block.
17375ffd83dbSDimitry Andric static bool isColdCallSite(CallBase &CB, BlockFrequencyInfo &CallerBFI) {
17380b57cec5SDimitry Andric   const BranchProbability ColdProb(ColdCCRelFreq, 100);
17395ffd83dbSDimitry Andric   auto *CallSiteBB = CB.getParent();
17400b57cec5SDimitry Andric   auto CallSiteFreq = CallerBFI.getBlockFreq(CallSiteBB);
17410b57cec5SDimitry Andric   auto CallerEntryFreq =
17425ffd83dbSDimitry Andric       CallerBFI.getBlockFreq(&(CB.getCaller()->getEntryBlock()));
17430b57cec5SDimitry Andric   return CallSiteFreq < CallerEntryFreq * ColdProb;
17440b57cec5SDimitry Andric }
17450b57cec5SDimitry Andric 
17460b57cec5SDimitry Andric // This function checks if the input function F is cold at all call sites. It
17470b57cec5SDimitry Andric // also looks each call site's containing function, returning false if the
17480b57cec5SDimitry Andric // caller function contains other non cold calls. The input vector AllCallsCold
17490b57cec5SDimitry Andric // contains a list of functions that only have call sites in cold blocks.
17500b57cec5SDimitry Andric static bool
17510b57cec5SDimitry Andric isValidCandidateForColdCC(Function &F,
17520b57cec5SDimitry Andric                           function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
17530b57cec5SDimitry Andric                           const std::vector<Function *> &AllCallsCold) {
17540b57cec5SDimitry Andric 
17550b57cec5SDimitry Andric   if (F.user_empty())
17560b57cec5SDimitry Andric     return false;
17570b57cec5SDimitry Andric 
17580b57cec5SDimitry Andric   for (User *U : F.users()) {
17590b57cec5SDimitry Andric     if (isa<BlockAddress>(U))
17600b57cec5SDimitry Andric       continue;
17610b57cec5SDimitry Andric 
17625ffd83dbSDimitry Andric     CallBase &CB = cast<CallBase>(*U);
17635ffd83dbSDimitry Andric     Function *CallerFunc = CB.getParent()->getParent();
17640b57cec5SDimitry Andric     BlockFrequencyInfo &CallerBFI = GetBFI(*CallerFunc);
17655ffd83dbSDimitry Andric     if (!isColdCallSite(CB, CallerBFI))
17660b57cec5SDimitry Andric       return false;
1767e8d8bef9SDimitry Andric     if (!llvm::is_contained(AllCallsCold, CallerFunc))
17680b57cec5SDimitry Andric       return false;
17690b57cec5SDimitry Andric   }
17700b57cec5SDimitry Andric   return true;
17710b57cec5SDimitry Andric }
17720b57cec5SDimitry Andric 
17730b57cec5SDimitry Andric static void changeCallSitesToColdCC(Function *F) {
17740b57cec5SDimitry Andric   for (User *U : F->users()) {
17750b57cec5SDimitry Andric     if (isa<BlockAddress>(U))
17760b57cec5SDimitry Andric       continue;
17775ffd83dbSDimitry Andric     cast<CallBase>(U)->setCallingConv(CallingConv::Cold);
17780b57cec5SDimitry Andric   }
17790b57cec5SDimitry Andric }
17800b57cec5SDimitry Andric 
17810b57cec5SDimitry Andric // This function iterates over all the call instructions in the input Function
17820b57cec5SDimitry Andric // and checks that all call sites are in cold blocks and are allowed to use the
17830b57cec5SDimitry Andric // coldcc calling convention.
17840b57cec5SDimitry Andric static bool
17850b57cec5SDimitry Andric hasOnlyColdCalls(Function &F,
1786b121cb00SDimitry Andric                  function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
1787b121cb00SDimitry Andric                  ChangeableCCCacheTy &ChangeableCCCache) {
17880b57cec5SDimitry Andric   for (BasicBlock &BB : F) {
17890b57cec5SDimitry Andric     for (Instruction &I : BB) {
17900b57cec5SDimitry Andric       if (CallInst *CI = dyn_cast<CallInst>(&I)) {
17910b57cec5SDimitry Andric         // Skip over isline asm instructions since they aren't function calls.
17920b57cec5SDimitry Andric         if (CI->isInlineAsm())
17930b57cec5SDimitry Andric           continue;
17940b57cec5SDimitry Andric         Function *CalledFn = CI->getCalledFunction();
17950b57cec5SDimitry Andric         if (!CalledFn)
17960b57cec5SDimitry Andric           return false;
179781ad6265SDimitry Andric         // Skip over intrinsics since they won't remain as function calls.
1798bdd1243dSDimitry Andric         // Important to do this check before the linkage check below so we
1799bdd1243dSDimitry Andric         // won't bail out on debug intrinsics, possibly making the generated
1800bdd1243dSDimitry Andric         // code dependent on the presence of debug info.
18010b57cec5SDimitry Andric         if (CalledFn->getIntrinsicID() != Intrinsic::not_intrinsic)
18020b57cec5SDimitry Andric           continue;
1803bdd1243dSDimitry Andric         if (!CalledFn->hasLocalLinkage())
1804bdd1243dSDimitry Andric           return false;
18050b57cec5SDimitry Andric         // Check if it's valid to use coldcc calling convention.
1806b121cb00SDimitry Andric         if (!hasChangeableCC(CalledFn, ChangeableCCCache))
18070b57cec5SDimitry Andric           return false;
18080b57cec5SDimitry Andric         BlockFrequencyInfo &CallerBFI = GetBFI(F);
18095ffd83dbSDimitry Andric         if (!isColdCallSite(*CI, CallerBFI))
18100b57cec5SDimitry Andric           return false;
18110b57cec5SDimitry Andric       }
18120b57cec5SDimitry Andric     }
18130b57cec5SDimitry Andric   }
18140b57cec5SDimitry Andric   return true;
18150b57cec5SDimitry Andric }
18160b57cec5SDimitry Andric 
18175ffd83dbSDimitry Andric static bool hasMustTailCallers(Function *F) {
18185ffd83dbSDimitry Andric   for (User *U : F->users()) {
18195ffd83dbSDimitry Andric     CallBase *CB = dyn_cast<CallBase>(U);
18205ffd83dbSDimitry Andric     if (!CB) {
18215ffd83dbSDimitry Andric       assert(isa<BlockAddress>(U) &&
18225ffd83dbSDimitry Andric              "Expected either CallBase or BlockAddress");
18235ffd83dbSDimitry Andric       continue;
18245ffd83dbSDimitry Andric     }
18255ffd83dbSDimitry Andric     if (CB->isMustTailCall())
18265ffd83dbSDimitry Andric       return true;
18275ffd83dbSDimitry Andric   }
18285ffd83dbSDimitry Andric   return false;
18295ffd83dbSDimitry Andric }
18305ffd83dbSDimitry Andric 
18315ffd83dbSDimitry Andric static bool hasInvokeCallers(Function *F) {
18325ffd83dbSDimitry Andric   for (User *U : F->users())
18335ffd83dbSDimitry Andric     if (isa<InvokeInst>(U))
18345ffd83dbSDimitry Andric       return true;
18355ffd83dbSDimitry Andric   return false;
18365ffd83dbSDimitry Andric }
18375ffd83dbSDimitry Andric 
18385ffd83dbSDimitry Andric static void RemovePreallocated(Function *F) {
18395ffd83dbSDimitry Andric   RemoveAttribute(F, Attribute::Preallocated);
18405ffd83dbSDimitry Andric 
18415ffd83dbSDimitry Andric   auto *M = F->getParent();
18425ffd83dbSDimitry Andric 
18435ffd83dbSDimitry Andric   IRBuilder<> Builder(M->getContext());
18445ffd83dbSDimitry Andric 
18455ffd83dbSDimitry Andric   // Cannot modify users() while iterating over it, so make a copy.
18465ffd83dbSDimitry Andric   SmallVector<User *, 4> PreallocatedCalls(F->users());
18475ffd83dbSDimitry Andric   for (User *U : PreallocatedCalls) {
18485ffd83dbSDimitry Andric     CallBase *CB = dyn_cast<CallBase>(U);
18495ffd83dbSDimitry Andric     if (!CB)
18505ffd83dbSDimitry Andric       continue;
18515ffd83dbSDimitry Andric 
18525ffd83dbSDimitry Andric     assert(
18535ffd83dbSDimitry Andric         !CB->isMustTailCall() &&
18545ffd83dbSDimitry Andric         "Shouldn't call RemotePreallocated() on a musttail preallocated call");
18555ffd83dbSDimitry Andric     // Create copy of call without "preallocated" operand bundle.
18565ffd83dbSDimitry Andric     SmallVector<OperandBundleDef, 1> OpBundles;
18575ffd83dbSDimitry Andric     CB->getOperandBundlesAsDefs(OpBundles);
18585ffd83dbSDimitry Andric     CallBase *PreallocatedSetup = nullptr;
18595ffd83dbSDimitry Andric     for (auto *It = OpBundles.begin(); It != OpBundles.end(); ++It) {
18605ffd83dbSDimitry Andric       if (It->getTag() == "preallocated") {
18615ffd83dbSDimitry Andric         PreallocatedSetup = cast<CallBase>(*It->input_begin());
18625ffd83dbSDimitry Andric         OpBundles.erase(It);
18635ffd83dbSDimitry Andric         break;
18645ffd83dbSDimitry Andric       }
18655ffd83dbSDimitry Andric     }
18665ffd83dbSDimitry Andric     assert(PreallocatedSetup && "Did not find preallocated bundle");
18675ffd83dbSDimitry Andric     uint64_t ArgCount =
18685ffd83dbSDimitry Andric         cast<ConstantInt>(PreallocatedSetup->getArgOperand(0))->getZExtValue();
18695ffd83dbSDimitry Andric 
18705ffd83dbSDimitry Andric     assert((isa<CallInst>(CB) || isa<InvokeInst>(CB)) &&
18715ffd83dbSDimitry Andric            "Unknown indirect call type");
1872*0fca6ea1SDimitry Andric     CallBase *NewCB = CallBase::Create(CB, OpBundles, CB->getIterator());
18735ffd83dbSDimitry Andric     CB->replaceAllUsesWith(NewCB);
18745ffd83dbSDimitry Andric     NewCB->takeName(CB);
18755ffd83dbSDimitry Andric     CB->eraseFromParent();
18765ffd83dbSDimitry Andric 
18775ffd83dbSDimitry Andric     Builder.SetInsertPoint(PreallocatedSetup);
18785f757f3fSDimitry Andric     auto *StackSave = Builder.CreateStackSave();
18795ffd83dbSDimitry Andric     Builder.SetInsertPoint(NewCB->getNextNonDebugInstruction());
18805f757f3fSDimitry Andric     Builder.CreateStackRestore(StackSave);
18815ffd83dbSDimitry Andric 
18825ffd83dbSDimitry Andric     // Replace @llvm.call.preallocated.arg() with alloca.
18835ffd83dbSDimitry Andric     // Cannot modify users() while iterating over it, so make a copy.
18845ffd83dbSDimitry Andric     // @llvm.call.preallocated.arg() can be called with the same index multiple
18855ffd83dbSDimitry Andric     // times. So for each @llvm.call.preallocated.arg(), we see if we have
18865ffd83dbSDimitry Andric     // already created a Value* for the index, and if not, create an alloca and
18875ffd83dbSDimitry Andric     // bitcast right after the @llvm.call.preallocated.setup() so that it
18885ffd83dbSDimitry Andric     // dominates all uses.
18895ffd83dbSDimitry Andric     SmallVector<Value *, 2> ArgAllocas(ArgCount);
18905ffd83dbSDimitry Andric     SmallVector<User *, 2> PreallocatedArgs(PreallocatedSetup->users());
18915ffd83dbSDimitry Andric     for (auto *User : PreallocatedArgs) {
18925ffd83dbSDimitry Andric       auto *UseCall = cast<CallBase>(User);
18935ffd83dbSDimitry Andric       assert(UseCall->getCalledFunction()->getIntrinsicID() ==
18945ffd83dbSDimitry Andric                  Intrinsic::call_preallocated_arg &&
18955ffd83dbSDimitry Andric              "preallocated token use was not a llvm.call.preallocated.arg");
18965ffd83dbSDimitry Andric       uint64_t AllocArgIndex =
18975ffd83dbSDimitry Andric           cast<ConstantInt>(UseCall->getArgOperand(1))->getZExtValue();
18985ffd83dbSDimitry Andric       Value *AllocaReplacement = ArgAllocas[AllocArgIndex];
18995ffd83dbSDimitry Andric       if (!AllocaReplacement) {
19005ffd83dbSDimitry Andric         auto AddressSpace = UseCall->getType()->getPointerAddressSpace();
1901349cc55cSDimitry Andric         auto *ArgType =
1902349cc55cSDimitry Andric             UseCall->getFnAttr(Attribute::Preallocated).getValueAsType();
19035ffd83dbSDimitry Andric         auto *InsertBefore = PreallocatedSetup->getNextNonDebugInstruction();
19045ffd83dbSDimitry Andric         Builder.SetInsertPoint(InsertBefore);
19055ffd83dbSDimitry Andric         auto *Alloca =
19065ffd83dbSDimitry Andric             Builder.CreateAlloca(ArgType, AddressSpace, nullptr, "paarg");
19075f757f3fSDimitry Andric         ArgAllocas[AllocArgIndex] = Alloca;
19085f757f3fSDimitry Andric         AllocaReplacement = Alloca;
19095ffd83dbSDimitry Andric       }
19105ffd83dbSDimitry Andric 
19115ffd83dbSDimitry Andric       UseCall->replaceAllUsesWith(AllocaReplacement);
19125ffd83dbSDimitry Andric       UseCall->eraseFromParent();
19135ffd83dbSDimitry Andric     }
19145ffd83dbSDimitry Andric     // Remove @llvm.call.preallocated.setup().
19155ffd83dbSDimitry Andric     cast<Instruction>(PreallocatedSetup)->eraseFromParent();
19165ffd83dbSDimitry Andric   }
19175ffd83dbSDimitry Andric }
19185ffd83dbSDimitry Andric 
19190b57cec5SDimitry Andric static bool
19208bcb0991SDimitry Andric OptimizeFunctions(Module &M,
19218bcb0991SDimitry Andric                   function_ref<TargetLibraryInfo &(Function &)> GetTLI,
19220b57cec5SDimitry Andric                   function_ref<TargetTransformInfo &(Function &)> GetTTI,
19230b57cec5SDimitry Andric                   function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
19240b57cec5SDimitry Andric                   function_ref<DominatorTree &(Function &)> LookupDomTree,
192581ad6265SDimitry Andric                   SmallPtrSetImpl<const Comdat *> &NotDiscardableComdats,
192681ad6265SDimitry Andric                   function_ref<void(Function &F)> ChangedCFGCallback,
192781ad6265SDimitry Andric                   function_ref<void(Function &F)> DeleteFnCallback) {
19280b57cec5SDimitry Andric 
19290b57cec5SDimitry Andric   bool Changed = false;
19300b57cec5SDimitry Andric 
1931b121cb00SDimitry Andric   ChangeableCCCacheTy ChangeableCCCache;
19320b57cec5SDimitry Andric   std::vector<Function *> AllCallsCold;
1933349cc55cSDimitry Andric   for (Function &F : llvm::make_early_inc_range(M))
1934b121cb00SDimitry Andric     if (hasOnlyColdCalls(F, GetBFI, ChangeableCCCache))
1935349cc55cSDimitry Andric       AllCallsCold.push_back(&F);
19360b57cec5SDimitry Andric 
19370b57cec5SDimitry Andric   // Optimize functions.
1938349cc55cSDimitry Andric   for (Function &F : llvm::make_early_inc_range(M)) {
19390b57cec5SDimitry Andric     // Don't perform global opt pass on naked functions; we don't want fast
19400b57cec5SDimitry Andric     // calling conventions for naked functions.
1941349cc55cSDimitry Andric     if (F.hasFnAttribute(Attribute::Naked))
19420b57cec5SDimitry Andric       continue;
19430b57cec5SDimitry Andric 
19440b57cec5SDimitry Andric     // Functions without names cannot be referenced outside this module.
1945349cc55cSDimitry Andric     if (!F.hasName() && !F.isDeclaration() && !F.hasLocalLinkage())
1946349cc55cSDimitry Andric       F.setLinkage(GlobalValue::InternalLinkage);
19470b57cec5SDimitry Andric 
194881ad6265SDimitry Andric     if (deleteIfDead(F, NotDiscardableComdats, DeleteFnCallback)) {
19490b57cec5SDimitry Andric       Changed = true;
19500b57cec5SDimitry Andric       continue;
19510b57cec5SDimitry Andric     }
19520b57cec5SDimitry Andric 
19530b57cec5SDimitry Andric     // LLVM's definition of dominance allows instructions that are cyclic
19540b57cec5SDimitry Andric     // in unreachable blocks, e.g.:
19550b57cec5SDimitry Andric     // %pat = select i1 %condition, @global, i16* %pat
19560b57cec5SDimitry Andric     // because any instruction dominates an instruction in a block that's
19570b57cec5SDimitry Andric     // not reachable from entry.
19580b57cec5SDimitry Andric     // So, remove unreachable blocks from the function, because a) there's
19590b57cec5SDimitry Andric     // no point in analyzing them and b) GlobalOpt should otherwise grow
19600b57cec5SDimitry Andric     // some more complicated logic to break these cycles.
196181ad6265SDimitry Andric     // Notify the analysis manager that we've modified the function's CFG.
1962349cc55cSDimitry Andric     if (!F.isDeclaration()) {
1963349cc55cSDimitry Andric       if (removeUnreachableBlocks(F)) {
1964480093f4SDimitry Andric         Changed = true;
196581ad6265SDimitry Andric         ChangedCFGCallback(F);
1966480093f4SDimitry Andric       }
19670b57cec5SDimitry Andric     }
19680b57cec5SDimitry Andric 
1969349cc55cSDimitry Andric     Changed |= processGlobal(F, GetTTI, GetTLI, LookupDomTree);
19700b57cec5SDimitry Andric 
1971349cc55cSDimitry Andric     if (!F.hasLocalLinkage())
19720b57cec5SDimitry Andric       continue;
19730b57cec5SDimitry Andric 
19740b57cec5SDimitry Andric     // If we have an inalloca parameter that we can safely remove the
19750b57cec5SDimitry Andric     // inalloca attribute from, do so. This unlocks optimizations that
19760b57cec5SDimitry Andric     // wouldn't be safe in the presence of inalloca.
19770b57cec5SDimitry Andric     // FIXME: We should also hoist alloca affected by this to the entry
19780b57cec5SDimitry Andric     // block if possible.
1979349cc55cSDimitry Andric     if (F.getAttributes().hasAttrSomewhere(Attribute::InAlloca) &&
1980f3fd488fSDimitry Andric         !F.hasAddressTaken() && !hasMustTailCallers(&F) && !F.isVarArg()) {
1981349cc55cSDimitry Andric       RemoveAttribute(&F, Attribute::InAlloca);
19820b57cec5SDimitry Andric       Changed = true;
19830b57cec5SDimitry Andric     }
19840b57cec5SDimitry Andric 
19855ffd83dbSDimitry Andric     // FIXME: handle invokes
19865ffd83dbSDimitry Andric     // FIXME: handle musttail
1987349cc55cSDimitry Andric     if (F.getAttributes().hasAttrSomewhere(Attribute::Preallocated)) {
1988349cc55cSDimitry Andric       if (!F.hasAddressTaken() && !hasMustTailCallers(&F) &&
1989349cc55cSDimitry Andric           !hasInvokeCallers(&F)) {
1990349cc55cSDimitry Andric         RemovePreallocated(&F);
19915ffd83dbSDimitry Andric         Changed = true;
19925ffd83dbSDimitry Andric       }
19935ffd83dbSDimitry Andric       continue;
19945ffd83dbSDimitry Andric     }
19955ffd83dbSDimitry Andric 
1996b121cb00SDimitry Andric     if (hasChangeableCC(&F, ChangeableCCCache)) {
19970b57cec5SDimitry Andric       NumInternalFunc++;
1998349cc55cSDimitry Andric       TargetTransformInfo &TTI = GetTTI(F);
19990b57cec5SDimitry Andric       // Change the calling convention to coldcc if either stress testing is
20000b57cec5SDimitry Andric       // enabled or the target would like to use coldcc on functions which are
20010b57cec5SDimitry Andric       // cold at all call sites and the callers contain no other non coldcc
20020b57cec5SDimitry Andric       // calls.
20030b57cec5SDimitry Andric       if (EnableColdCCStressTest ||
2004349cc55cSDimitry Andric           (TTI.useColdCCForColdCall(F) &&
2005349cc55cSDimitry Andric            isValidCandidateForColdCC(F, GetBFI, AllCallsCold))) {
2006b121cb00SDimitry Andric         ChangeableCCCache.erase(&F);
2007349cc55cSDimitry Andric         F.setCallingConv(CallingConv::Cold);
2008349cc55cSDimitry Andric         changeCallSitesToColdCC(&F);
20090b57cec5SDimitry Andric         Changed = true;
20100b57cec5SDimitry Andric         NumColdCC++;
20110b57cec5SDimitry Andric       }
20120b57cec5SDimitry Andric     }
20130b57cec5SDimitry Andric 
2014b121cb00SDimitry Andric     if (hasChangeableCC(&F, ChangeableCCCache)) {
20150b57cec5SDimitry Andric       // If this function has a calling convention worth changing, is not a
20160b57cec5SDimitry Andric       // varargs function, and is only called directly, promote it to use the
20170b57cec5SDimitry Andric       // Fast calling convention.
2018349cc55cSDimitry Andric       F.setCallingConv(CallingConv::Fast);
2019349cc55cSDimitry Andric       ChangeCalleesToFastCall(&F);
20200b57cec5SDimitry Andric       ++NumFastCallFns;
20210b57cec5SDimitry Andric       Changed = true;
20220b57cec5SDimitry Andric     }
20230b57cec5SDimitry Andric 
2024349cc55cSDimitry Andric     if (F.getAttributes().hasAttrSomewhere(Attribute::Nest) &&
2025349cc55cSDimitry Andric         !F.hasAddressTaken()) {
20260b57cec5SDimitry Andric       // The function is not used by a trampoline intrinsic, so it is safe
20270b57cec5SDimitry Andric       // to remove the 'nest' attribute.
2028349cc55cSDimitry Andric       RemoveAttribute(&F, Attribute::Nest);
20290b57cec5SDimitry Andric       ++NumNestRemoved;
20300b57cec5SDimitry Andric       Changed = true;
20310b57cec5SDimitry Andric     }
20320b57cec5SDimitry Andric   }
20330b57cec5SDimitry Andric   return Changed;
20340b57cec5SDimitry Andric }
20350b57cec5SDimitry Andric 
20360b57cec5SDimitry Andric static bool
20378bcb0991SDimitry Andric OptimizeGlobalVars(Module &M,
2038349cc55cSDimitry Andric                    function_ref<TargetTransformInfo &(Function &)> GetTTI,
20398bcb0991SDimitry Andric                    function_ref<TargetLibraryInfo &(Function &)> GetTLI,
20400b57cec5SDimitry Andric                    function_ref<DominatorTree &(Function &)> LookupDomTree,
20410b57cec5SDimitry Andric                    SmallPtrSetImpl<const Comdat *> &NotDiscardableComdats) {
20420b57cec5SDimitry Andric   bool Changed = false;
20430b57cec5SDimitry Andric 
2044349cc55cSDimitry Andric   for (GlobalVariable &GV : llvm::make_early_inc_range(M.globals())) {
20450b57cec5SDimitry Andric     // Global variables without names cannot be referenced outside this module.
2046349cc55cSDimitry Andric     if (!GV.hasName() && !GV.isDeclaration() && !GV.hasLocalLinkage())
2047349cc55cSDimitry Andric       GV.setLinkage(GlobalValue::InternalLinkage);
20480b57cec5SDimitry Andric     // Simplify the initializer.
2049349cc55cSDimitry Andric     if (GV.hasInitializer())
2050349cc55cSDimitry Andric       if (auto *C = dyn_cast<Constant>(GV.getInitializer())) {
20510b57cec5SDimitry Andric         auto &DL = M.getDataLayout();
20528bcb0991SDimitry Andric         // TLI is not used in the case of a Constant, so use default nullptr
20538bcb0991SDimitry Andric         // for that optional parameter, since we don't have a Function to
20548bcb0991SDimitry Andric         // provide GetTLI anyway.
20558bcb0991SDimitry Andric         Constant *New = ConstantFoldConstant(C, DL, /*TLI*/ nullptr);
20565ffd83dbSDimitry Andric         if (New != C)
2057349cc55cSDimitry Andric           GV.setInitializer(New);
20580b57cec5SDimitry Andric       }
20590b57cec5SDimitry Andric 
2060349cc55cSDimitry Andric     if (deleteIfDead(GV, NotDiscardableComdats)) {
20610b57cec5SDimitry Andric       Changed = true;
20620b57cec5SDimitry Andric       continue;
20630b57cec5SDimitry Andric     }
20640b57cec5SDimitry Andric 
2065349cc55cSDimitry Andric     Changed |= processGlobal(GV, GetTTI, GetTLI, LookupDomTree);
20660b57cec5SDimitry Andric   }
20670b57cec5SDimitry Andric   return Changed;
20680b57cec5SDimitry Andric }
20690b57cec5SDimitry Andric 
20700b57cec5SDimitry Andric /// Evaluate static constructors in the function, if we can.  Return true if we
20710b57cec5SDimitry Andric /// can, false otherwise.
20720b57cec5SDimitry Andric static bool EvaluateStaticConstructor(Function *F, const DataLayout &DL,
20730b57cec5SDimitry Andric                                       TargetLibraryInfo *TLI) {
207481ad6265SDimitry Andric   // Skip external functions.
207581ad6265SDimitry Andric   if (F->isDeclaration())
207681ad6265SDimitry Andric     return false;
20770b57cec5SDimitry Andric   // Call the function.
20780b57cec5SDimitry Andric   Evaluator Eval(DL, TLI);
20790b57cec5SDimitry Andric   Constant *RetValDummy;
20800b57cec5SDimitry Andric   bool EvalSuccess = Eval.EvaluateFunction(F, RetValDummy,
20810b57cec5SDimitry Andric                                            SmallVector<Constant*, 0>());
20820b57cec5SDimitry Andric 
20830b57cec5SDimitry Andric   if (EvalSuccess) {
20840b57cec5SDimitry Andric     ++NumCtorsEvaluated;
20850b57cec5SDimitry Andric 
20860b57cec5SDimitry Andric     // We succeeded at evaluation: commit the result.
208704eeddc0SDimitry Andric     auto NewInitializers = Eval.getMutatedInitializers();
20880b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "FULLY EVALUATED GLOBAL CTOR FUNCTION '"
208904eeddc0SDimitry Andric                       << F->getName() << "' to " << NewInitializers.size()
209004eeddc0SDimitry Andric                       << " stores.\n");
209104eeddc0SDimitry Andric     for (const auto &Pair : NewInitializers)
209204eeddc0SDimitry Andric       Pair.first->setInitializer(Pair.second);
20930b57cec5SDimitry Andric     for (GlobalVariable *GV : Eval.getInvariants())
20940b57cec5SDimitry Andric       GV->setConstant(true);
20950b57cec5SDimitry Andric   }
20960b57cec5SDimitry Andric 
20970b57cec5SDimitry Andric   return EvalSuccess;
20980b57cec5SDimitry Andric }
20990b57cec5SDimitry Andric 
21000b57cec5SDimitry Andric static int compareNames(Constant *const *A, Constant *const *B) {
21018bcb0991SDimitry Andric   Value *AStripped = (*A)->stripPointerCasts();
21028bcb0991SDimitry Andric   Value *BStripped = (*B)->stripPointerCasts();
21030b57cec5SDimitry Andric   return AStripped->getName().compare(BStripped->getName());
21040b57cec5SDimitry Andric }
21050b57cec5SDimitry Andric 
21060b57cec5SDimitry Andric static void setUsedInitializer(GlobalVariable &V,
21070b57cec5SDimitry Andric                                const SmallPtrSetImpl<GlobalValue *> &Init) {
21080b57cec5SDimitry Andric   if (Init.empty()) {
21090b57cec5SDimitry Andric     V.eraseFromParent();
21100b57cec5SDimitry Andric     return;
21110b57cec5SDimitry Andric   }
21120b57cec5SDimitry Andric 
211306c3fb27SDimitry Andric   // Get address space of pointers in the array of pointers.
211406c3fb27SDimitry Andric   const Type *UsedArrayType = V.getValueType();
211506c3fb27SDimitry Andric   const auto *VAT = cast<ArrayType>(UsedArrayType);
211606c3fb27SDimitry Andric   const auto *VEPT = cast<PointerType>(VAT->getArrayElementType());
211706c3fb27SDimitry Andric 
21180b57cec5SDimitry Andric   // Type of pointer to the array of pointers.
21195f757f3fSDimitry Andric   PointerType *PtrTy =
21205f757f3fSDimitry Andric       PointerType::get(V.getContext(), VEPT->getAddressSpace());
21210b57cec5SDimitry Andric 
21220b57cec5SDimitry Andric   SmallVector<Constant *, 8> UsedArray;
21230b57cec5SDimitry Andric   for (GlobalValue *GV : Init) {
21245f757f3fSDimitry Andric     Constant *Cast = ConstantExpr::getPointerBitCastOrAddrSpaceCast(GV, PtrTy);
21250b57cec5SDimitry Andric     UsedArray.push_back(Cast);
21260b57cec5SDimitry Andric   }
212706c3fb27SDimitry Andric 
21280b57cec5SDimitry Andric   // Sort to get deterministic order.
21290b57cec5SDimitry Andric   array_pod_sort(UsedArray.begin(), UsedArray.end(), compareNames);
21305f757f3fSDimitry Andric   ArrayType *ATy = ArrayType::get(PtrTy, UsedArray.size());
21310b57cec5SDimitry Andric 
21320b57cec5SDimitry Andric   Module *M = V.getParent();
21330b57cec5SDimitry Andric   V.removeFromParent();
21340b57cec5SDimitry Andric   GlobalVariable *NV =
21350b57cec5SDimitry Andric       new GlobalVariable(*M, ATy, false, GlobalValue::AppendingLinkage,
21360b57cec5SDimitry Andric                          ConstantArray::get(ATy, UsedArray), "");
21370b57cec5SDimitry Andric   NV->takeName(&V);
21380b57cec5SDimitry Andric   NV->setSection("llvm.metadata");
21390b57cec5SDimitry Andric   delete &V;
21400b57cec5SDimitry Andric }
21410b57cec5SDimitry Andric 
21420b57cec5SDimitry Andric namespace {
21430b57cec5SDimitry Andric 
21440b57cec5SDimitry Andric /// An easy to access representation of llvm.used and llvm.compiler.used.
21450b57cec5SDimitry Andric class LLVMUsed {
2146fe6060f1SDimitry Andric   SmallPtrSet<GlobalValue *, 4> Used;
2147fe6060f1SDimitry Andric   SmallPtrSet<GlobalValue *, 4> CompilerUsed;
21480b57cec5SDimitry Andric   GlobalVariable *UsedV;
21490b57cec5SDimitry Andric   GlobalVariable *CompilerUsedV;
21500b57cec5SDimitry Andric 
21510b57cec5SDimitry Andric public:
21520b57cec5SDimitry Andric   LLVMUsed(Module &M) {
2153fe6060f1SDimitry Andric     SmallVector<GlobalValue *, 4> Vec;
2154fe6060f1SDimitry Andric     UsedV = collectUsedGlobalVariables(M, Vec, false);
2155fe6060f1SDimitry Andric     Used = {Vec.begin(), Vec.end()};
2156fe6060f1SDimitry Andric     Vec.clear();
2157fe6060f1SDimitry Andric     CompilerUsedV = collectUsedGlobalVariables(M, Vec, true);
2158fe6060f1SDimitry Andric     CompilerUsed = {Vec.begin(), Vec.end()};
21590b57cec5SDimitry Andric   }
21600b57cec5SDimitry Andric 
2161fe6060f1SDimitry Andric   using iterator = SmallPtrSet<GlobalValue *, 4>::iterator;
21620b57cec5SDimitry Andric   using used_iterator_range = iterator_range<iterator>;
21630b57cec5SDimitry Andric 
21640b57cec5SDimitry Andric   iterator usedBegin() { return Used.begin(); }
21650b57cec5SDimitry Andric   iterator usedEnd() { return Used.end(); }
21660b57cec5SDimitry Andric 
21670b57cec5SDimitry Andric   used_iterator_range used() {
21680b57cec5SDimitry Andric     return used_iterator_range(usedBegin(), usedEnd());
21690b57cec5SDimitry Andric   }
21700b57cec5SDimitry Andric 
21710b57cec5SDimitry Andric   iterator compilerUsedBegin() { return CompilerUsed.begin(); }
21720b57cec5SDimitry Andric   iterator compilerUsedEnd() { return CompilerUsed.end(); }
21730b57cec5SDimitry Andric 
21740b57cec5SDimitry Andric   used_iterator_range compilerUsed() {
21750b57cec5SDimitry Andric     return used_iterator_range(compilerUsedBegin(), compilerUsedEnd());
21760b57cec5SDimitry Andric   }
21770b57cec5SDimitry Andric 
21780b57cec5SDimitry Andric   bool usedCount(GlobalValue *GV) const { return Used.count(GV); }
21790b57cec5SDimitry Andric 
21800b57cec5SDimitry Andric   bool compilerUsedCount(GlobalValue *GV) const {
21810b57cec5SDimitry Andric     return CompilerUsed.count(GV);
21820b57cec5SDimitry Andric   }
21830b57cec5SDimitry Andric 
21840b57cec5SDimitry Andric   bool usedErase(GlobalValue *GV) { return Used.erase(GV); }
21850b57cec5SDimitry Andric   bool compilerUsedErase(GlobalValue *GV) { return CompilerUsed.erase(GV); }
21860b57cec5SDimitry Andric   bool usedInsert(GlobalValue *GV) { return Used.insert(GV).second; }
21870b57cec5SDimitry Andric 
21880b57cec5SDimitry Andric   bool compilerUsedInsert(GlobalValue *GV) {
21890b57cec5SDimitry Andric     return CompilerUsed.insert(GV).second;
21900b57cec5SDimitry Andric   }
21910b57cec5SDimitry Andric 
21920b57cec5SDimitry Andric   void syncVariablesAndSets() {
21930b57cec5SDimitry Andric     if (UsedV)
21940b57cec5SDimitry Andric       setUsedInitializer(*UsedV, Used);
21950b57cec5SDimitry Andric     if (CompilerUsedV)
21960b57cec5SDimitry Andric       setUsedInitializer(*CompilerUsedV, CompilerUsed);
21970b57cec5SDimitry Andric   }
21980b57cec5SDimitry Andric };
21990b57cec5SDimitry Andric 
22000b57cec5SDimitry Andric } // end anonymous namespace
22010b57cec5SDimitry Andric 
22020b57cec5SDimitry Andric static bool hasUseOtherThanLLVMUsed(GlobalAlias &GA, const LLVMUsed &U) {
22030b57cec5SDimitry Andric   if (GA.use_empty()) // No use at all.
22040b57cec5SDimitry Andric     return false;
22050b57cec5SDimitry Andric 
22060b57cec5SDimitry Andric   assert((!U.usedCount(&GA) || !U.compilerUsedCount(&GA)) &&
22070b57cec5SDimitry Andric          "We should have removed the duplicated "
22080b57cec5SDimitry Andric          "element from llvm.compiler.used");
22090b57cec5SDimitry Andric   if (!GA.hasOneUse())
22100b57cec5SDimitry Andric     // Strictly more than one use. So at least one is not in llvm.used and
22110b57cec5SDimitry Andric     // llvm.compiler.used.
22120b57cec5SDimitry Andric     return true;
22130b57cec5SDimitry Andric 
22140b57cec5SDimitry Andric   // Exactly one use. Check if it is in llvm.used or llvm.compiler.used.
22150b57cec5SDimitry Andric   return !U.usedCount(&GA) && !U.compilerUsedCount(&GA);
22160b57cec5SDimitry Andric }
22170b57cec5SDimitry Andric 
221806c3fb27SDimitry Andric static bool mayHaveOtherReferences(GlobalValue &GV, const LLVMUsed &U) {
221906c3fb27SDimitry Andric   if (!GV.hasLocalLinkage())
22200b57cec5SDimitry Andric     return true;
22210b57cec5SDimitry Andric 
222206c3fb27SDimitry Andric   return U.usedCount(&GV) || U.compilerUsedCount(&GV);
22230b57cec5SDimitry Andric }
22240b57cec5SDimitry Andric 
22250b57cec5SDimitry Andric static bool hasUsesToReplace(GlobalAlias &GA, const LLVMUsed &U,
22260b57cec5SDimitry Andric                              bool &RenameTarget) {
22273a079333SDimitry Andric   if (GA.isWeakForLinker())
22283a079333SDimitry Andric     return false;
22293a079333SDimitry Andric 
22300b57cec5SDimitry Andric   RenameTarget = false;
22310b57cec5SDimitry Andric   bool Ret = false;
22320b57cec5SDimitry Andric   if (hasUseOtherThanLLVMUsed(GA, U))
22330b57cec5SDimitry Andric     Ret = true;
22340b57cec5SDimitry Andric 
22350b57cec5SDimitry Andric   // If the alias is externally visible, we may still be able to simplify it.
22360b57cec5SDimitry Andric   if (!mayHaveOtherReferences(GA, U))
22370b57cec5SDimitry Andric     return Ret;
22380b57cec5SDimitry Andric 
223906c3fb27SDimitry Andric   // If the aliasee has internal linkage and no other references (e.g.,
224006c3fb27SDimitry Andric   // @llvm.used, @llvm.compiler.used), give it the name and linkage of the
224106c3fb27SDimitry Andric   // alias, and delete the alias. This turns:
22420b57cec5SDimitry Andric   //   define internal ... @f(...)
22430b57cec5SDimitry Andric   //   @a = alias ... @f
22440b57cec5SDimitry Andric   // into:
22450b57cec5SDimitry Andric   //   define ... @a(...)
22460b57cec5SDimitry Andric   Constant *Aliasee = GA.getAliasee();
22470b57cec5SDimitry Andric   GlobalValue *Target = cast<GlobalValue>(Aliasee->stripPointerCasts());
224806c3fb27SDimitry Andric   if (mayHaveOtherReferences(*Target, U))
22490b57cec5SDimitry Andric     return Ret;
22500b57cec5SDimitry Andric 
22510b57cec5SDimitry Andric   RenameTarget = true;
22520b57cec5SDimitry Andric   return true;
22530b57cec5SDimitry Andric }
22540b57cec5SDimitry Andric 
22550b57cec5SDimitry Andric static bool
22560b57cec5SDimitry Andric OptimizeGlobalAliases(Module &M,
22570b57cec5SDimitry Andric                       SmallPtrSetImpl<const Comdat *> &NotDiscardableComdats) {
22580b57cec5SDimitry Andric   bool Changed = false;
22590b57cec5SDimitry Andric   LLVMUsed Used(M);
22600b57cec5SDimitry Andric 
22610b57cec5SDimitry Andric   for (GlobalValue *GV : Used.used())
22620b57cec5SDimitry Andric     Used.compilerUsedErase(GV);
22630b57cec5SDimitry Andric 
22641fd87a68SDimitry Andric   // Return whether GV is explicitly or implicitly dso_local and not replaceable
22651fd87a68SDimitry Andric   // by another definition in the current linkage unit.
22661fd87a68SDimitry Andric   auto IsModuleLocal = [](GlobalValue &GV) {
22671fd87a68SDimitry Andric     return !GlobalValue::isInterposableLinkage(GV.getLinkage()) &&
22681fd87a68SDimitry Andric            (GV.isDSOLocal() || GV.isImplicitDSOLocal());
22691fd87a68SDimitry Andric   };
22701fd87a68SDimitry Andric 
2271349cc55cSDimitry Andric   for (GlobalAlias &J : llvm::make_early_inc_range(M.aliases())) {
22720b57cec5SDimitry Andric     // Aliases without names cannot be referenced outside this module.
2273349cc55cSDimitry Andric     if (!J.hasName() && !J.isDeclaration() && !J.hasLocalLinkage())
2274349cc55cSDimitry Andric       J.setLinkage(GlobalValue::InternalLinkage);
22750b57cec5SDimitry Andric 
2276349cc55cSDimitry Andric     if (deleteIfDead(J, NotDiscardableComdats)) {
22770b57cec5SDimitry Andric       Changed = true;
22780b57cec5SDimitry Andric       continue;
22790b57cec5SDimitry Andric     }
22800b57cec5SDimitry Andric 
22810b57cec5SDimitry Andric     // If the alias can change at link time, nothing can be done - bail out.
22821fd87a68SDimitry Andric     if (!IsModuleLocal(J))
22830b57cec5SDimitry Andric       continue;
22840b57cec5SDimitry Andric 
2285349cc55cSDimitry Andric     Constant *Aliasee = J.getAliasee();
22860b57cec5SDimitry Andric     GlobalValue *Target = dyn_cast<GlobalValue>(Aliasee->stripPointerCasts());
22870b57cec5SDimitry Andric     // We can't trivially replace the alias with the aliasee if the aliasee is
2288fe6060f1SDimitry Andric     // non-trivial in some way. We also can't replace the alias with the aliasee
22891fd87a68SDimitry Andric     // if the aliasee may be preemptible at runtime. On ELF, a non-preemptible
22901fd87a68SDimitry Andric     // alias can be used to access the definition as if preemption did not
22911fd87a68SDimitry Andric     // happen.
22920b57cec5SDimitry Andric     // TODO: Try to handle non-zero GEPs of local aliasees.
22931fd87a68SDimitry Andric     if (!Target || !IsModuleLocal(*Target))
22940b57cec5SDimitry Andric       continue;
22951fd87a68SDimitry Andric 
22960b57cec5SDimitry Andric     Target->removeDeadConstantUsers();
22970b57cec5SDimitry Andric 
22980b57cec5SDimitry Andric     // Make all users of the alias use the aliasee instead.
22990b57cec5SDimitry Andric     bool RenameTarget;
2300349cc55cSDimitry Andric     if (!hasUsesToReplace(J, Used, RenameTarget))
23010b57cec5SDimitry Andric       continue;
23020b57cec5SDimitry Andric 
23035f757f3fSDimitry Andric     J.replaceAllUsesWith(Aliasee);
23040b57cec5SDimitry Andric     ++NumAliasesResolved;
23050b57cec5SDimitry Andric     Changed = true;
23060b57cec5SDimitry Andric 
23070b57cec5SDimitry Andric     if (RenameTarget) {
23080b57cec5SDimitry Andric       // Give the aliasee the name, linkage and other attributes of the alias.
2309349cc55cSDimitry Andric       Target->takeName(&J);
2310349cc55cSDimitry Andric       Target->setLinkage(J.getLinkage());
2311349cc55cSDimitry Andric       Target->setDSOLocal(J.isDSOLocal());
2312349cc55cSDimitry Andric       Target->setVisibility(J.getVisibility());
2313349cc55cSDimitry Andric       Target->setDLLStorageClass(J.getDLLStorageClass());
23140b57cec5SDimitry Andric 
2315349cc55cSDimitry Andric       if (Used.usedErase(&J))
23160b57cec5SDimitry Andric         Used.usedInsert(Target);
23170b57cec5SDimitry Andric 
2318349cc55cSDimitry Andric       if (Used.compilerUsedErase(&J))
23190b57cec5SDimitry Andric         Used.compilerUsedInsert(Target);
2320349cc55cSDimitry Andric     } else if (mayHaveOtherReferences(J, Used))
23210b57cec5SDimitry Andric       continue;
23220b57cec5SDimitry Andric 
23230b57cec5SDimitry Andric     // Delete the alias.
232406c3fb27SDimitry Andric     M.eraseAlias(&J);
23250b57cec5SDimitry Andric     ++NumAliasesRemoved;
23260b57cec5SDimitry Andric     Changed = true;
23270b57cec5SDimitry Andric   }
23280b57cec5SDimitry Andric 
23290b57cec5SDimitry Andric   Used.syncVariablesAndSets();
23300b57cec5SDimitry Andric 
23310b57cec5SDimitry Andric   return Changed;
23320b57cec5SDimitry Andric }
23330b57cec5SDimitry Andric 
23348bcb0991SDimitry Andric static Function *
2335*0fca6ea1SDimitry Andric FindAtExitLibFunc(Module &M,
2336*0fca6ea1SDimitry Andric                   function_ref<TargetLibraryInfo &(Function &)> GetTLI,
2337*0fca6ea1SDimitry Andric                   LibFunc Func) {
23388bcb0991SDimitry Andric   // Hack to get a default TLI before we have actual Function.
23398bcb0991SDimitry Andric   auto FuncIter = M.begin();
23408bcb0991SDimitry Andric   if (FuncIter == M.end())
23418bcb0991SDimitry Andric     return nullptr;
23428bcb0991SDimitry Andric   auto *TLI = &GetTLI(*FuncIter);
23438bcb0991SDimitry Andric 
2344*0fca6ea1SDimitry Andric   if (!TLI->has(Func))
23450b57cec5SDimitry Andric     return nullptr;
23460b57cec5SDimitry Andric 
2347*0fca6ea1SDimitry Andric   Function *Fn = M.getFunction(TLI->getName(Func));
23480b57cec5SDimitry Andric   if (!Fn)
23490b57cec5SDimitry Andric     return nullptr;
23500b57cec5SDimitry Andric 
23518bcb0991SDimitry Andric   // Now get the actual TLI for Fn.
23528bcb0991SDimitry Andric   TLI = &GetTLI(*Fn);
23538bcb0991SDimitry Andric 
23540b57cec5SDimitry Andric   // Make sure that the function has the correct prototype.
2355*0fca6ea1SDimitry Andric   LibFunc F;
2356*0fca6ea1SDimitry Andric   if (!TLI->getLibFunc(*Fn, F) || F != Func)
23570b57cec5SDimitry Andric     return nullptr;
23580b57cec5SDimitry Andric 
23590b57cec5SDimitry Andric   return Fn;
23600b57cec5SDimitry Andric }
23610b57cec5SDimitry Andric 
2362*0fca6ea1SDimitry Andric /// Returns whether the given function is an empty C++ destructor or atexit
2363*0fca6ea1SDimitry Andric /// handler and can therefore be eliminated. Note that we assume that other
2364*0fca6ea1SDimitry Andric /// optimization passes have already simplified the code so we simply check for
2365*0fca6ea1SDimitry Andric /// 'ret'.
2366*0fca6ea1SDimitry Andric static bool IsEmptyAtExitFunction(const Function &Fn) {
23670b57cec5SDimitry Andric   // FIXME: We could eliminate C++ destructors if they're readonly/readnone and
23680b57cec5SDimitry Andric   // nounwind, but that doesn't seem worth doing.
23690b57cec5SDimitry Andric   if (Fn.isDeclaration())
23700b57cec5SDimitry Andric     return false;
23710b57cec5SDimitry Andric 
2372bdd1243dSDimitry Andric   for (const auto &I : Fn.getEntryBlock()) {
2373349cc55cSDimitry Andric     if (I.isDebugOrPseudoInst())
23740b57cec5SDimitry Andric       continue;
23750b57cec5SDimitry Andric     if (isa<ReturnInst>(I))
23760b57cec5SDimitry Andric       return true;
23770b57cec5SDimitry Andric     break;
23780b57cec5SDimitry Andric   }
23790b57cec5SDimitry Andric   return false;
23800b57cec5SDimitry Andric }
23810b57cec5SDimitry Andric 
2382*0fca6ea1SDimitry Andric static bool OptimizeEmptyGlobalAtExitDtors(Function *CXAAtExitFn, bool isCXX) {
23830b57cec5SDimitry Andric   /// Itanium C++ ABI p3.3.5:
23840b57cec5SDimitry Andric   ///
23850b57cec5SDimitry Andric   ///   After constructing a global (or local static) object, that will require
23860b57cec5SDimitry Andric   ///   destruction on exit, a termination function is registered as follows:
23870b57cec5SDimitry Andric   ///
23880b57cec5SDimitry Andric   ///   extern "C" int __cxa_atexit ( void (*f)(void *), void *p, void *d );
23890b57cec5SDimitry Andric   ///
23900b57cec5SDimitry Andric   ///   This registration, e.g. __cxa_atexit(f,p,d), is intended to cause the
23910b57cec5SDimitry Andric   ///   call f(p) when DSO d is unloaded, before all such termination calls
23920b57cec5SDimitry Andric   ///   registered before this one. It returns zero if registration is
23930b57cec5SDimitry Andric   ///   successful, nonzero on failure.
23940b57cec5SDimitry Andric 
2395*0fca6ea1SDimitry Andric   // This pass will look for calls to __cxa_atexit or atexit where the function
2396*0fca6ea1SDimitry Andric   // is trivial and remove them.
23970b57cec5SDimitry Andric   bool Changed = false;
23980b57cec5SDimitry Andric 
2399349cc55cSDimitry Andric   for (User *U : llvm::make_early_inc_range(CXAAtExitFn->users())) {
24000b57cec5SDimitry Andric     // We're only interested in calls. Theoretically, we could handle invoke
24010b57cec5SDimitry Andric     // instructions as well, but neither llvm-gcc nor clang generate invokes
24020b57cec5SDimitry Andric     // to __cxa_atexit.
2403349cc55cSDimitry Andric     CallInst *CI = dyn_cast<CallInst>(U);
24040b57cec5SDimitry Andric     if (!CI)
24050b57cec5SDimitry Andric       continue;
24060b57cec5SDimitry Andric 
24070b57cec5SDimitry Andric     Function *DtorFn =
24080b57cec5SDimitry Andric       dyn_cast<Function>(CI->getArgOperand(0)->stripPointerCasts());
2409*0fca6ea1SDimitry Andric     if (!DtorFn || !IsEmptyAtExitFunction(*DtorFn))
24100b57cec5SDimitry Andric       continue;
24110b57cec5SDimitry Andric 
24120b57cec5SDimitry Andric     // Just remove the call.
24130b57cec5SDimitry Andric     CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
24140b57cec5SDimitry Andric     CI->eraseFromParent();
24150b57cec5SDimitry Andric 
2416*0fca6ea1SDimitry Andric     if (isCXX)
24170b57cec5SDimitry Andric       ++NumCXXDtorsRemoved;
2418*0fca6ea1SDimitry Andric     else
2419*0fca6ea1SDimitry Andric       ++NumAtExitRemoved;
24200b57cec5SDimitry Andric 
24210b57cec5SDimitry Andric     Changed |= true;
24220b57cec5SDimitry Andric   }
24230b57cec5SDimitry Andric 
24240b57cec5SDimitry Andric   return Changed;
24250b57cec5SDimitry Andric }
24260b57cec5SDimitry Andric 
2427*0fca6ea1SDimitry Andric static Function *hasSideeffectFreeStaticResolution(GlobalIFunc &IF) {
2428*0fca6ea1SDimitry Andric   if (IF.isInterposable())
2429*0fca6ea1SDimitry Andric     return nullptr;
2430*0fca6ea1SDimitry Andric 
2431*0fca6ea1SDimitry Andric   Function *Resolver = IF.getResolverFunction();
2432*0fca6ea1SDimitry Andric   if (!Resolver)
2433*0fca6ea1SDimitry Andric     return nullptr;
2434*0fca6ea1SDimitry Andric 
2435*0fca6ea1SDimitry Andric   if (Resolver->isInterposable())
2436*0fca6ea1SDimitry Andric     return nullptr;
2437*0fca6ea1SDimitry Andric 
2438*0fca6ea1SDimitry Andric   // Only handle functions that have been optimized into a single basic block.
2439*0fca6ea1SDimitry Andric   auto It = Resolver->begin();
2440*0fca6ea1SDimitry Andric   if (++It != Resolver->end())
2441*0fca6ea1SDimitry Andric     return nullptr;
2442*0fca6ea1SDimitry Andric 
2443*0fca6ea1SDimitry Andric   BasicBlock &BB = Resolver->getEntryBlock();
2444*0fca6ea1SDimitry Andric 
2445*0fca6ea1SDimitry Andric   if (any_of(BB, [](Instruction &I) { return I.mayHaveSideEffects(); }))
2446*0fca6ea1SDimitry Andric     return nullptr;
2447*0fca6ea1SDimitry Andric 
2448*0fca6ea1SDimitry Andric   auto *Ret = dyn_cast<ReturnInst>(BB.getTerminator());
2449*0fca6ea1SDimitry Andric   if (!Ret)
2450*0fca6ea1SDimitry Andric     return nullptr;
2451*0fca6ea1SDimitry Andric 
2452*0fca6ea1SDimitry Andric   return dyn_cast<Function>(Ret->getReturnValue());
2453*0fca6ea1SDimitry Andric }
2454*0fca6ea1SDimitry Andric 
2455*0fca6ea1SDimitry Andric /// Find IFuncs that have resolvers that always point at the same statically
2456*0fca6ea1SDimitry Andric /// known callee, and replace their callers with a direct call.
2457*0fca6ea1SDimitry Andric static bool OptimizeStaticIFuncs(Module &M) {
2458*0fca6ea1SDimitry Andric   bool Changed = false;
2459*0fca6ea1SDimitry Andric   for (GlobalIFunc &IF : M.ifuncs())
2460*0fca6ea1SDimitry Andric     if (Function *Callee = hasSideeffectFreeStaticResolution(IF))
2461*0fca6ea1SDimitry Andric       if (!IF.use_empty() &&
2462*0fca6ea1SDimitry Andric           (!Callee->isDeclaration() ||
2463*0fca6ea1SDimitry Andric            none_of(IF.users(), [](User *U) { return isa<GlobalAlias>(U); }))) {
2464*0fca6ea1SDimitry Andric         IF.replaceAllUsesWith(Callee);
2465*0fca6ea1SDimitry Andric         NumIFuncsResolved++;
2466*0fca6ea1SDimitry Andric         Changed = true;
2467*0fca6ea1SDimitry Andric       }
2468*0fca6ea1SDimitry Andric   return Changed;
2469*0fca6ea1SDimitry Andric }
2470*0fca6ea1SDimitry Andric 
2471*0fca6ea1SDimitry Andric static bool
2472*0fca6ea1SDimitry Andric DeleteDeadIFuncs(Module &M,
2473*0fca6ea1SDimitry Andric                  SmallPtrSetImpl<const Comdat *> &NotDiscardableComdats) {
2474*0fca6ea1SDimitry Andric   bool Changed = false;
2475*0fca6ea1SDimitry Andric   for (GlobalIFunc &IF : make_early_inc_range(M.ifuncs()))
2476*0fca6ea1SDimitry Andric     if (deleteIfDead(IF, NotDiscardableComdats)) {
2477*0fca6ea1SDimitry Andric       NumIFuncsDeleted++;
2478*0fca6ea1SDimitry Andric       Changed = true;
2479*0fca6ea1SDimitry Andric     }
2480*0fca6ea1SDimitry Andric   return Changed;
2481*0fca6ea1SDimitry Andric }
2482*0fca6ea1SDimitry Andric 
248381ad6265SDimitry Andric static bool
248481ad6265SDimitry Andric optimizeGlobalsInModule(Module &M, const DataLayout &DL,
24858bcb0991SDimitry Andric                         function_ref<TargetLibraryInfo &(Function &)> GetTLI,
24860b57cec5SDimitry Andric                         function_ref<TargetTransformInfo &(Function &)> GetTTI,
24870b57cec5SDimitry Andric                         function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
248881ad6265SDimitry Andric                         function_ref<DominatorTree &(Function &)> LookupDomTree,
248981ad6265SDimitry Andric                         function_ref<void(Function &F)> ChangedCFGCallback,
249081ad6265SDimitry Andric                         function_ref<void(Function &F)> DeleteFnCallback) {
24910b57cec5SDimitry Andric   SmallPtrSet<const Comdat *, 8> NotDiscardableComdats;
24920b57cec5SDimitry Andric   bool Changed = false;
24930b57cec5SDimitry Andric   bool LocalChange = true;
2494bdd1243dSDimitry Andric   std::optional<uint32_t> FirstNotFullyEvaluatedPriority;
249581ad6265SDimitry Andric 
24960b57cec5SDimitry Andric   while (LocalChange) {
24970b57cec5SDimitry Andric     LocalChange = false;
24980b57cec5SDimitry Andric 
24990b57cec5SDimitry Andric     NotDiscardableComdats.clear();
25000b57cec5SDimitry Andric     for (const GlobalVariable &GV : M.globals())
25010b57cec5SDimitry Andric       if (const Comdat *C = GV.getComdat())
25020b57cec5SDimitry Andric         if (!GV.isDiscardableIfUnused() || !GV.use_empty())
25030b57cec5SDimitry Andric           NotDiscardableComdats.insert(C);
25040b57cec5SDimitry Andric     for (Function &F : M)
25050b57cec5SDimitry Andric       if (const Comdat *C = F.getComdat())
25060b57cec5SDimitry Andric         if (!F.isDefTriviallyDead())
25070b57cec5SDimitry Andric           NotDiscardableComdats.insert(C);
25080b57cec5SDimitry Andric     for (GlobalAlias &GA : M.aliases())
25090b57cec5SDimitry Andric       if (const Comdat *C = GA.getComdat())
25100b57cec5SDimitry Andric         if (!GA.isDiscardableIfUnused() || !GA.use_empty())
25110b57cec5SDimitry Andric           NotDiscardableComdats.insert(C);
25120b57cec5SDimitry Andric 
25130b57cec5SDimitry Andric     // Delete functions that are trivially dead, ccc -> fastcc
25148bcb0991SDimitry Andric     LocalChange |= OptimizeFunctions(M, GetTLI, GetTTI, GetBFI, LookupDomTree,
251581ad6265SDimitry Andric                                      NotDiscardableComdats, ChangedCFGCallback,
251681ad6265SDimitry Andric                                      DeleteFnCallback);
25170b57cec5SDimitry Andric 
25180b57cec5SDimitry Andric     // Optimize global_ctors list.
251981ad6265SDimitry Andric     LocalChange |=
252081ad6265SDimitry Andric         optimizeGlobalCtorsList(M, [&](uint32_t Priority, Function *F) {
252181ad6265SDimitry Andric           if (FirstNotFullyEvaluatedPriority &&
252281ad6265SDimitry Andric               *FirstNotFullyEvaluatedPriority != Priority)
252381ad6265SDimitry Andric             return false;
252481ad6265SDimitry Andric           bool Evaluated = EvaluateStaticConstructor(F, DL, &GetTLI(*F));
252581ad6265SDimitry Andric           if (!Evaluated)
252681ad6265SDimitry Andric             FirstNotFullyEvaluatedPriority = Priority;
252781ad6265SDimitry Andric           return Evaluated;
25280b57cec5SDimitry Andric         });
25290b57cec5SDimitry Andric 
25300b57cec5SDimitry Andric     // Optimize non-address-taken globals.
2531349cc55cSDimitry Andric     LocalChange |= OptimizeGlobalVars(M, GetTTI, GetTLI, LookupDomTree,
2532349cc55cSDimitry Andric                                       NotDiscardableComdats);
25330b57cec5SDimitry Andric 
25340b57cec5SDimitry Andric     // Resolve aliases, when possible.
25350b57cec5SDimitry Andric     LocalChange |= OptimizeGlobalAliases(M, NotDiscardableComdats);
25360b57cec5SDimitry Andric 
25370b57cec5SDimitry Andric     // Try to remove trivial global destructors if they are not removed
25380b57cec5SDimitry Andric     // already.
2539*0fca6ea1SDimitry Andric     if (Function *CXAAtExitFn =
2540*0fca6ea1SDimitry Andric             FindAtExitLibFunc(M, GetTLI, LibFunc_cxa_atexit))
2541*0fca6ea1SDimitry Andric       LocalChange |= OptimizeEmptyGlobalAtExitDtors(CXAAtExitFn, true);
2542*0fca6ea1SDimitry Andric 
2543*0fca6ea1SDimitry Andric     if (Function *AtExitFn = FindAtExitLibFunc(M, GetTLI, LibFunc_atexit))
2544*0fca6ea1SDimitry Andric       LocalChange |= OptimizeEmptyGlobalAtExitDtors(AtExitFn, false);
2545*0fca6ea1SDimitry Andric 
2546*0fca6ea1SDimitry Andric     // Optimize IFuncs whose callee's are statically known.
2547*0fca6ea1SDimitry Andric     LocalChange |= OptimizeStaticIFuncs(M);
2548*0fca6ea1SDimitry Andric 
2549*0fca6ea1SDimitry Andric     // Remove any IFuncs that are now dead.
2550*0fca6ea1SDimitry Andric     LocalChange |= DeleteDeadIFuncs(M, NotDiscardableComdats);
25510b57cec5SDimitry Andric 
25520b57cec5SDimitry Andric     Changed |= LocalChange;
25530b57cec5SDimitry Andric   }
25540b57cec5SDimitry Andric 
25550b57cec5SDimitry Andric   // TODO: Move all global ctors functions to the end of the module for code
25560b57cec5SDimitry Andric   // layout.
25570b57cec5SDimitry Andric 
25580b57cec5SDimitry Andric   return Changed;
25590b57cec5SDimitry Andric }
25600b57cec5SDimitry Andric 
25610b57cec5SDimitry Andric PreservedAnalyses GlobalOptPass::run(Module &M, ModuleAnalysisManager &AM) {
25620b57cec5SDimitry Andric     auto &DL = M.getDataLayout();
25630b57cec5SDimitry Andric     auto &FAM =
25640b57cec5SDimitry Andric         AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
25650b57cec5SDimitry Andric     auto LookupDomTree = [&FAM](Function &F) -> DominatorTree &{
25660b57cec5SDimitry Andric       return FAM.getResult<DominatorTreeAnalysis>(F);
25670b57cec5SDimitry Andric     };
25688bcb0991SDimitry Andric     auto GetTLI = [&FAM](Function &F) -> TargetLibraryInfo & {
25698bcb0991SDimitry Andric       return FAM.getResult<TargetLibraryAnalysis>(F);
25708bcb0991SDimitry Andric     };
25710b57cec5SDimitry Andric     auto GetTTI = [&FAM](Function &F) -> TargetTransformInfo & {
25720b57cec5SDimitry Andric       return FAM.getResult<TargetIRAnalysis>(F);
25730b57cec5SDimitry Andric     };
25740b57cec5SDimitry Andric 
25750b57cec5SDimitry Andric     auto GetBFI = [&FAM](Function &F) -> BlockFrequencyInfo & {
25760b57cec5SDimitry Andric       return FAM.getResult<BlockFrequencyAnalysis>(F);
25770b57cec5SDimitry Andric     };
257881ad6265SDimitry Andric     auto ChangedCFGCallback = [&FAM](Function &F) {
257981ad6265SDimitry Andric       FAM.invalidate(F, PreservedAnalyses::none());
258081ad6265SDimitry Andric     };
258181ad6265SDimitry Andric     auto DeleteFnCallback = [&FAM](Function &F) { FAM.clear(F, F.getName()); };
25820b57cec5SDimitry Andric 
258381ad6265SDimitry Andric     if (!optimizeGlobalsInModule(M, DL, GetTLI, GetTTI, GetBFI, LookupDomTree,
258481ad6265SDimitry Andric                                  ChangedCFGCallback, DeleteFnCallback))
25850b57cec5SDimitry Andric       return PreservedAnalyses::all();
258681ad6265SDimitry Andric 
258781ad6265SDimitry Andric     PreservedAnalyses PA = PreservedAnalyses::none();
258881ad6265SDimitry Andric     // We made sure to clear analyses for deleted functions.
258981ad6265SDimitry Andric     PA.preserve<FunctionAnalysisManagerModuleProxy>();
259081ad6265SDimitry Andric     // The only place we modify the CFG is when calling
259181ad6265SDimitry Andric     // removeUnreachableBlocks(), but there we make sure to invalidate analyses
259281ad6265SDimitry Andric     // for modified functions.
259381ad6265SDimitry Andric     PA.preserveSet<CFGAnalyses>();
259481ad6265SDimitry Andric     return PA;
25950b57cec5SDimitry Andric }
2596