#include "llvm/Transforms/IPO/GlobalOpt.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/Twine.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Analysis/BlockFrequencyInfo.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Use.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/AtomicOrdering.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Utils/CtorUtils.h"
#include "llvm/Transforms/Utils/Evaluator.h"
#include "llvm/Transforms/Utils/GlobalStatus.h"
#include "llvm/Transforms/Utils/Local.h"
#include <cassert>
#include <cstdint>
#include <optional>
#include <utility>
#include <vector>
usingnamespacellvm;
#define DEBUG_TYPE …
STATISTIC(NumMarked , "Number of globals marked constant");
STATISTIC(NumUnnamed , "Number of globals marked unnamed_addr");
STATISTIC(NumSRA , "Number of aggregate globals broken into scalars");
STATISTIC(NumSubstitute,"Number of globals with initializers stored into them");
STATISTIC(NumDeleted , "Number of globals deleted");
STATISTIC(NumGlobUses , "Number of global uses devirtualized");
STATISTIC(NumLocalized , "Number of globals localized");
STATISTIC(NumShrunkToBool , "Number of global vars shrunk to booleans");
STATISTIC(NumFastCallFns , "Number of functions converted to fastcc");
STATISTIC(NumCtorsEvaluated, "Number of static ctors evaluated");
STATISTIC(NumNestRemoved , "Number of nest attributes removed");
STATISTIC(NumAliasesResolved, "Number of global aliases resolved");
STATISTIC(NumAliasesRemoved, "Number of global aliases eliminated");
STATISTIC(NumCXXDtorsRemoved, "Number of global C++ destructors removed");
STATISTIC(NumAtExitRemoved, "Number of atexit handlers removed");
STATISTIC(NumInternalFunc, "Number of internal functions");
STATISTIC(NumColdCC, "Number of functions marked coldcc");
STATISTIC(NumIFuncsResolved, "Number of statically resolved IFuncs");
STATISTIC(NumIFuncsDeleted, "Number of IFuncs removed");
static cl::opt<bool>
EnableColdCCStressTest("enable-coldcc-stress-test",
cl::desc("Enable stress test of coldcc by adding "
"calling conv to all internal functions."),
cl::init(false), cl::Hidden);
static cl::opt<int> ColdCCRelFreq(
"coldcc-rel-freq", cl::Hidden, cl::init(2),
cl::desc(
"Maximum block frequency, expressed as a percentage of caller's "
"entry frequency, for a call site to be considered cold for enabling"
"coldcc"));
static bool isLeakCheckerRoot(GlobalVariable *GV) { … }
static bool IsSafeComputationToRemove(
Value *V, function_ref<TargetLibraryInfo &(Function &)> GetTLI) { … }
static bool
CleanupPointerRootUsers(GlobalVariable *GV,
function_ref<TargetLibraryInfo &(Function &)> GetTLI) { … }
static bool CleanupConstantGlobalUsers(GlobalVariable *GV,
const DataLayout &DL) { … }
struct GlobalPart { … };
static bool collectSRATypes(DenseMap<uint64_t, GlobalPart> &Parts,
GlobalVariable *GV, const DataLayout &DL) { … }
static void transferSRADebugInfo(GlobalVariable *GV, GlobalVariable *NGV,
uint64_t FragmentOffsetInBits,
uint64_t FragmentSizeInBits,
uint64_t VarSize) { … }
static GlobalVariable *SRAGlobal(GlobalVariable *GV, const DataLayout &DL) { … }
static bool AllUsesOfValueWillTrapIfNull(const Value *V,
SmallPtrSetImpl<const PHINode*> &PHIs) { … }
static bool allUsesOfLoadedValueWillTrapIfNull(const GlobalVariable *GV) { … }
static void allUsesOfLoadAndStores(GlobalVariable *GV,
SmallVector<Value *, 4> &Uses) { … }
static bool OptimizeAwayTrappingUsesOfValue(Value *V, Constant *NewV) { … }
static bool OptimizeAwayTrappingUsesOfLoads(
GlobalVariable *GV, Constant *LV, const DataLayout &DL,
function_ref<TargetLibraryInfo &(Function &)> GetTLI) { … }
static void ConstantPropUsersOf(Value *V, const DataLayout &DL,
TargetLibraryInfo *TLI) { … }
static GlobalVariable *
OptimizeGlobalAddressOfAllocation(GlobalVariable *GV, CallInst *CI,
uint64_t AllocSize, Constant *InitVal,
const DataLayout &DL,
TargetLibraryInfo *TLI) { … }
static bool
valueIsOnlyUsedLocallyOrStoredToOneGlobal(const CallInst *CI,
const GlobalVariable *GV) { … }
static bool tryToOptimizeStoreOfAllocationToGlobal(GlobalVariable *GV,
CallInst *CI,
const DataLayout &DL,
TargetLibraryInfo *TLI) { … }
static bool
optimizeOnceStoredGlobal(GlobalVariable *GV, Value *StoredOnceVal,
const DataLayout &DL,
function_ref<TargetLibraryInfo &(Function &)> GetTLI) { … }
static bool TryToShrinkGlobalToBoolean(GlobalVariable *GV, Constant *OtherVal) { … }
static bool
deleteIfDead(GlobalValue &GV,
SmallPtrSetImpl<const Comdat *> &NotDiscardableComdats,
function_ref<void(Function &)> DeleteFnCallback = nullptr) { … }
static bool isPointerValueDeadOnEntryToFunction(
const Function *F, GlobalValue *GV,
function_ref<DominatorTree &(Function &)> LookupDomTree) { … }
static bool forwardStoredOnceStore(
GlobalVariable *GV, const StoreInst *StoredOnceStore,
function_ref<DominatorTree &(Function &)> LookupDomTree) { … }
static bool
processInternalGlobal(GlobalVariable *GV, const GlobalStatus &GS,
function_ref<TargetTransformInfo &(Function &)> GetTTI,
function_ref<TargetLibraryInfo &(Function &)> GetTLI,
function_ref<DominatorTree &(Function &)> LookupDomTree) { … }
static bool
processGlobal(GlobalValue &GV,
function_ref<TargetTransformInfo &(Function &)> GetTTI,
function_ref<TargetLibraryInfo &(Function &)> GetTLI,
function_ref<DominatorTree &(Function &)> LookupDomTree) { … }
static void ChangeCalleesToFastCall(Function *F) { … }
static AttributeList StripAttr(LLVMContext &C, AttributeList Attrs,
Attribute::AttrKind A) { … }
static void RemoveAttribute(Function *F, Attribute::AttrKind A) { … }
static bool hasChangeableCCImpl(Function *F) { … }
ChangeableCCCacheTy;
static bool hasChangeableCC(Function *F,
ChangeableCCCacheTy &ChangeableCCCache) { … }
static bool isColdCallSite(CallBase &CB, BlockFrequencyInfo &CallerBFI) { … }
static bool
isValidCandidateForColdCC(Function &F,
function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
const std::vector<Function *> &AllCallsCold) { … }
static void changeCallSitesToColdCC(Function *F) { … }
static bool
hasOnlyColdCalls(Function &F,
function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
ChangeableCCCacheTy &ChangeableCCCache) { … }
static bool hasMustTailCallers(Function *F) { … }
static bool hasInvokeCallers(Function *F) { … }
static void RemovePreallocated(Function *F) { … }
static bool
OptimizeFunctions(Module &M,
function_ref<TargetLibraryInfo &(Function &)> GetTLI,
function_ref<TargetTransformInfo &(Function &)> GetTTI,
function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
function_ref<DominatorTree &(Function &)> LookupDomTree,
SmallPtrSetImpl<const Comdat *> &NotDiscardableComdats,
function_ref<void(Function &F)> ChangedCFGCallback,
function_ref<void(Function &F)> DeleteFnCallback) { … }
static bool
OptimizeGlobalVars(Module &M,
function_ref<TargetTransformInfo &(Function &)> GetTTI,
function_ref<TargetLibraryInfo &(Function &)> GetTLI,
function_ref<DominatorTree &(Function &)> LookupDomTree,
SmallPtrSetImpl<const Comdat *> &NotDiscardableComdats) { … }
static bool EvaluateStaticConstructor(Function *F, const DataLayout &DL,
TargetLibraryInfo *TLI) { … }
static int compareNames(Constant *const *A, Constant *const *B) { … }
static void setUsedInitializer(GlobalVariable &V,
const SmallPtrSetImpl<GlobalValue *> &Init) { … }
namespace {
class LLVMUsed { … };
}
static bool hasUseOtherThanLLVMUsed(GlobalAlias &GA, const LLVMUsed &U) { … }
static bool mayHaveOtherReferences(GlobalValue &GV, const LLVMUsed &U) { … }
static bool hasUsesToReplace(GlobalAlias &GA, const LLVMUsed &U,
bool &RenameTarget) { … }
static bool
OptimizeGlobalAliases(Module &M,
SmallPtrSetImpl<const Comdat *> &NotDiscardableComdats) { … }
static Function *
FindAtExitLibFunc(Module &M,
function_ref<TargetLibraryInfo &(Function &)> GetTLI,
LibFunc Func) { … }
static bool IsEmptyAtExitFunction(const Function &Fn) { … }
static bool OptimizeEmptyGlobalAtExitDtors(Function *CXAAtExitFn, bool isCXX) { … }
static Function *hasSideeffectFreeStaticResolution(GlobalIFunc &IF) { … }
static bool OptimizeStaticIFuncs(Module &M) { … }
static bool
DeleteDeadIFuncs(Module &M,
SmallPtrSetImpl<const Comdat *> &NotDiscardableComdats) { … }
static bool
optimizeGlobalsInModule(Module &M, const DataLayout &DL,
function_ref<TargetLibraryInfo &(Function &)> GetTLI,
function_ref<TargetTransformInfo &(Function &)> GetTTI,
function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
function_ref<DominatorTree &(Function &)> LookupDomTree,
function_ref<void(Function &F)> ChangedCFGCallback,
function_ref<void(Function &F)> DeleteFnCallback) { … }
PreservedAnalyses GlobalOptPass::run(Module &M, ModuleAnalysisManager &AM) { … }