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