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.
isLeakCheckerRoot(GlobalVariable * GV)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.
IsSafeComputationToRemove(Value * V,function_ref<TargetLibraryInfo & (Function &)> GetTLI)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
CleanupPointerRootUsers(GlobalVariable * GV,function_ref<TargetLibraryInfo & (Function &)> GetTLI)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.
CleanupConstantGlobalUsers(GlobalVariable * GV,const DataLayout & DL)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.
collectSRATypes(DenseMap<uint64_t,GlobalPart> & Parts,GlobalVariable * GV,const DataLayout & DL)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.
transferSRADebugInfo(GlobalVariable * GV,GlobalVariable * NGV,uint64_t FragmentOffsetInBits,uint64_t FragmentSizeInBits,uint64_t VarSize)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.
SRAGlobal(GlobalVariable * GV,const DataLayout & DL)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.
AllUsesOfValueWillTrapIfNull(const Value * V,SmallPtrSetImpl<const PHINode * > & PHIs)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.
allUsesOfLoadedValueWillTrapIfNull(const GlobalVariable * GV)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.
allUsesOfLoadAndStores(GlobalVariable * GV,SmallVector<Value *,4> & Uses)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
OptimizeAwayTrappingUsesOfValue(Value * V,Constant * NewV)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.
OptimizeAwayTrappingUsesOfLoads(GlobalVariable * GV,Constant * LV,const DataLayout & DL,function_ref<TargetLibraryInfo & (Function &)> GetTLI)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.
ConstantPropUsersOf(Value * V,const DataLayout & DL,TargetLibraryInfo * TLI)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 *
OptimizeGlobalAddressOfAllocation(GlobalVariable * GV,CallInst * CI,uint64_t AllocSize,Constant * InitVal,const DataLayout & DL,TargetLibraryInfo * TLI)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
valueIsOnlyUsedLocallyOrStoredToOneGlobal(const CallInst * CI,const GlobalVariable * GV)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.
tryToOptimizeStoreOfAllocationToGlobal(GlobalVariable * GV,CallInst * CI,const DataLayout & DL,TargetLibraryInfo * TLI)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
optimizeOnceStoredGlobal(GlobalVariable * GV,Value * StoredOnceVal,const DataLayout & DL,function_ref<TargetLibraryInfo & (Function &)> GetTLI)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.
TryToShrinkGlobalToBoolean(GlobalVariable * GV,Constant * OtherVal)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
deleteIfDead(GlobalValue & GV,SmallPtrSetImpl<const Comdat * > & NotDiscardableComdats,function_ref<void (Function &)> DeleteFnCallback=nullptr)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
isPointerValueDeadOnEntryToFunction(const Function * F,GlobalValue * GV,function_ref<DominatorTree & (Function &)> LookupDomTree)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.
forwardStoredOnceStore(GlobalVariable * GV,const StoreInst * StoredOnceStore,function_ref<DominatorTree & (Function &)> LookupDomTree)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
processInternalGlobal(GlobalVariable * GV,const GlobalStatus & GS,function_ref<TargetTransformInfo & (Function &)> GetTTI,function_ref<TargetLibraryInfo & (Function &)> GetTLI,function_ref<DominatorTree & (Function &)> LookupDomTree)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
processGlobal(GlobalValue & GV,function_ref<TargetTransformInfo & (Function &)> GetTTI,function_ref<TargetLibraryInfo & (Function &)> GetTLI,function_ref<DominatorTree & (Function &)> LookupDomTree)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.
ChangeCalleesToFastCall(Function * F)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
StripAttr(LLVMContext & C,AttributeList Attrs,Attribute::AttrKind A)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
RemoveAttribute(Function * F,Attribute::AttrKind A)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.
hasChangeableCCImpl(Function * F)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>;
hasChangeableCC(Function * F,ChangeableCCCacheTy & ChangeableCCCache)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.
isColdCallSite(CallBase & CB,BlockFrequencyInfo & CallerBFI)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
isValidCandidateForColdCC(Function & F,function_ref<BlockFrequencyInfo & (Function &)> GetBFI,const std::vector<Function * > & AllCallsCold)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
changeCallSitesToColdCC(Function * F)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
hasOnlyColdCalls(Function & F,function_ref<BlockFrequencyInfo & (Function &)> GetBFI,ChangeableCCCacheTy & ChangeableCCCache)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
hasMustTailCallers(Function * F)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
hasInvokeCallers(Function * F)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
RemovePreallocated(Function * F)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
OptimizeFunctions(Module & M,function_ref<TargetLibraryInfo & (Function &)> GetTLI,function_ref<TargetTransformInfo & (Function &)> GetTTI,function_ref<BlockFrequencyInfo & (Function &)> GetBFI,function_ref<DominatorTree & (Function &)> LookupDomTree,SmallPtrSetImpl<const Comdat * > & NotDiscardableComdats,function_ref<void (Function & F)> ChangedCFGCallback,function_ref<void (Function & F)> DeleteFnCallback)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
OptimizeGlobalVars(Module & M,function_ref<TargetTransformInfo & (Function &)> GetTTI,function_ref<TargetLibraryInfo & (Function &)> GetTLI,function_ref<DominatorTree & (Function &)> LookupDomTree,SmallPtrSetImpl<const Comdat * > & NotDiscardableComdats)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.
EvaluateStaticConstructor(Function * F,const DataLayout & DL,TargetLibraryInfo * TLI)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
compareNames(Constant * const * A,Constant * const * B)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
setUsedInitializer(GlobalVariable & V,const SmallPtrSetImpl<GlobalValue * > & Init)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:
LLVMUsed(Module & M)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
usedBegin()21640b57cec5SDimitry Andric iterator usedBegin() { return Used.begin(); }
usedEnd()21650b57cec5SDimitry Andric iterator usedEnd() { return Used.end(); }
21660b57cec5SDimitry Andric
used()21670b57cec5SDimitry Andric used_iterator_range used() {
21680b57cec5SDimitry Andric return used_iterator_range(usedBegin(), usedEnd());
21690b57cec5SDimitry Andric }
21700b57cec5SDimitry Andric
compilerUsedBegin()21710b57cec5SDimitry Andric iterator compilerUsedBegin() { return CompilerUsed.begin(); }
compilerUsedEnd()21720b57cec5SDimitry Andric iterator compilerUsedEnd() { return CompilerUsed.end(); }
21730b57cec5SDimitry Andric
compilerUsed()21740b57cec5SDimitry Andric used_iterator_range compilerUsed() {
21750b57cec5SDimitry Andric return used_iterator_range(compilerUsedBegin(), compilerUsedEnd());
21760b57cec5SDimitry Andric }
21770b57cec5SDimitry Andric
usedCount(GlobalValue * GV) const21780b57cec5SDimitry Andric bool usedCount(GlobalValue *GV) const { return Used.count(GV); }
21790b57cec5SDimitry Andric
compilerUsedCount(GlobalValue * GV) const21800b57cec5SDimitry Andric bool compilerUsedCount(GlobalValue *GV) const {
21810b57cec5SDimitry Andric return CompilerUsed.count(GV);
21820b57cec5SDimitry Andric }
21830b57cec5SDimitry Andric
usedErase(GlobalValue * GV)21840b57cec5SDimitry Andric bool usedErase(GlobalValue *GV) { return Used.erase(GV); }
compilerUsedErase(GlobalValue * GV)21850b57cec5SDimitry Andric bool compilerUsedErase(GlobalValue *GV) { return CompilerUsed.erase(GV); }
usedInsert(GlobalValue * GV)21860b57cec5SDimitry Andric bool usedInsert(GlobalValue *GV) { return Used.insert(GV).second; }
21870b57cec5SDimitry Andric
compilerUsedInsert(GlobalValue * GV)21880b57cec5SDimitry Andric bool compilerUsedInsert(GlobalValue *GV) {
21890b57cec5SDimitry Andric return CompilerUsed.insert(GV).second;
21900b57cec5SDimitry Andric }
21910b57cec5SDimitry Andric
syncVariablesAndSets()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
hasUseOtherThanLLVMUsed(GlobalAlias & GA,const LLVMUsed & U)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
mayHaveOtherReferences(GlobalValue & GV,const LLVMUsed & U)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
hasUsesToReplace(GlobalAlias & GA,const LLVMUsed & U,bool & RenameTarget)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
OptimizeGlobalAliases(Module & M,SmallPtrSetImpl<const Comdat * > & NotDiscardableComdats)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 *
FindAtExitLibFunc(Module & M,function_ref<TargetLibraryInfo & (Function &)> GetTLI,LibFunc Func)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'.
IsEmptyAtExitFunction(const Function & Fn)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
OptimizeEmptyGlobalAtExitDtors(Function * CXAAtExitFn,bool isCXX)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
hasSideeffectFreeStaticResolution(GlobalIFunc & IF)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.
OptimizeStaticIFuncs(Module & M)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
DeleteDeadIFuncs(Module & M,SmallPtrSetImpl<const Comdat * > & NotDiscardableComdats)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
optimizeGlobalsInModule(Module & M,const DataLayout & DL,function_ref<TargetLibraryInfo & (Function &)> GetTLI,function_ref<TargetTransformInfo & (Function &)> GetTTI,function_ref<BlockFrequencyInfo & (Function &)> GetBFI,function_ref<DominatorTree & (Function &)> LookupDomTree,function_ref<void (Function & F)> ChangedCFGCallback,function_ref<void (Function & F)> DeleteFnCallback)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
run(Module & M,ModuleAnalysisManager & AM)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