38#define DEBUG_TYPE "stack-safety"
40STATISTIC(NumAllocaStackSafe,
"Number of safe allocas");
41STATISTIC(NumAllocaTotal,
"Number of total allocas");
44 "Number of total callee lookups on combined index.");
46 "Number of failed callee lookups on combined index.");
48 "Number of total callee lookups on module index.");
50 "Number of failed callee lookups on module index.");
52 "Number of total param accesses before generateParamAccessSummary.");
54 "Number of total param accesses after generateParamAccessSummary.");
56 "Number of total nodes in combined index for dataflow processing.");
57STATISTIC(NumIndexCalleeUnhandled,
"Number of index callee which are unhandled.");
58STATISTIC(NumIndexCalleeMultipleWeak,
"Number of index callee non-unique weak.");
59STATISTIC(NumIndexCalleeMultipleExternal,
"Number of index callee non-unique external.");
75 return R.isEmptySet() || R.isFullSet() || R.isUpperSignWrapped();
81 if (
L.signedAddMayOverflow(R) !=
82 ConstantRange::OverflowResult::NeverOverflows)
83 return ConstantRange::getFull(
L.getBitWidth());
94 if (
Result.isSignWrappedSet())
100template <
typename CalleeTy>
struct CallInfo {
102 const CalleeTy *
Callee =
nullptr;
106 CallInfo(
const CalleeTy *Callee,
size_t ParamNo)
111 return std::tie(
L.ParamNo,
L.Callee) < std::tie(
R.ParamNo,
R.Callee);
117template <
typename CalleeTy>
struct UseInfo {
121 std::set<const Instruction *> UnsafeAccesses;
137 UnsafeAccesses.insert(
I);
142template <
typename CalleeTy>
145 for (
auto &Call :
U.Calls)
147 <<
"@" <<
Call.first.Callee->getName() <<
"(arg" <<
Call.first.ParamNo
148 <<
", " <<
Call.second <<
")";
163 if (APSize.isNonPositive())
169 bool Overflow =
false;
171 if (
Mul.isNonPositive())
173 Mul =
Mul.sextOrTrunc(PointerSize);
174 APSize = APSize.smul_ov(
Mul, Overflow);
183template <
typename CalleeTy>
struct FunctionInfo {
184 std::map<const AllocaInst *, UseInfo<CalleeTy>> Allocas;
185 std::map<uint32_t, UseInfo<CalleeTy>> Params;
194 O <<
" @" <<
Name << ((
F &&
F->isDSOLocal()) ?
"" :
" dso_preemptable")
195 << ((
F &&
F->isInterposable()) ?
" interposable" :
"") <<
"\n";
197 O <<
" args uses:\n";
198 for (
auto &KV : Params) {
201 O <<
F->getArg(KV.first)->getName();
204 O <<
"[]: " << KV.second <<
"\n";
207 O <<
" allocas uses:\n";
210 if (
const AllocaInst *AI = dyn_cast<AllocaInst>(&
I)) {
211 auto &AS = Allocas.find(AI)->second;
213 << getStaticAllocaSizeRange(*AI).getUpper() <<
"]: " << AS <<
"\n";
222using GVToSSI = std::map<const GlobalValue *, FunctionInfo<GlobalValue>>;
227 FunctionInfo<GlobalValue>
Info;
238class StackSafetyLocalAnalysis {
242 unsigned PointerSize = 0;
253 void analyzeAllUses(
Value *
Ptr, UseInfo<GlobalValue> &AS,
263 :
F(
F),
DL(
F.getParent()->getDataLayout()), SE(SE),
264 PointerSize(
DL.getPointerSizeInBits()),
265 UnknownRange(PointerSize,
true) {}
268 FunctionInfo<GlobalValue> run();
272 if (!SE.isSCEVable(
Addr->getType()) || !SE.isSCEVable(
Base->getType()))
275 auto *PtrTy = IntegerType::getInt8PtrTy(SE.getContext());
276 const SCEV *AddrExp = SE.getTruncateOrZeroExtend(SE.getSCEV(
Addr), PtrTy);
277 const SCEV *BaseExp = SE.getTruncateOrZeroExtend(SE.getSCEV(
Base), PtrTy);
278 const SCEV *Diff = SE.getMinusSCEV(AddrExp, BaseExp);
279 if (isa<SCEVCouldNotCompute>(Diff))
285 return Offset.sextOrTrunc(PointerSize);
293 return ConstantRange::getEmpty(PointerSize);
294 assert(!isUnsafe(SizeRange));
297 if (isUnsafe(Offsets))
300 Offsets = addOverflowNever(Offsets, SizeRange);
301 if (isUnsafe(Offsets))
308 if (
Size.isScalable())
310 APInt APSize(PointerSize,
Size.getFixedValue(),
true);
311 if (APSize.isNegative())
317ConstantRange StackSafetyLocalAnalysis::getMemIntrinsicAccessRange(
319 if (
const auto *MTI = dyn_cast<MemTransferInst>(
MI)) {
320 if (MTI->getRawSource() != U && MTI->getRawDest() != U)
321 return ConstantRange::getEmpty(PointerSize);
323 if (
MI->getRawDest() != U)
324 return ConstantRange::getEmpty(PointerSize);
327 auto *CalculationTy = IntegerType::getIntNTy(SE.getContext(), PointerSize);
328 if (!SE.isSCEVable(
MI->getLength()->getType()))
332 SE.getTruncateOrZeroExtend(SE.getSCEV(
MI->getLength()), CalculationTy);
334 if (
Sizes.getUpper().isNegative() || isUnsafe(Sizes))
338 return getAccessRange(U,
Base, SizeRange);
341bool StackSafetyLocalAnalysis::isSafeAccess(
const Use &U,
AllocaInst *AI,
343 return isSafeAccess(U, AI, SE.getSCEV(V));
346bool StackSafetyLocalAnalysis::isSafeAccess(
const Use &U,
AllocaInst *AI,
350 auto *CalculationTy = IntegerType::getIntNTy(SE.getContext(), PointerSize);
352 return isSafeAccess(U, AI, SV);
355bool StackSafetyLocalAnalysis::isSafeAccess(
const Use &U,
AllocaInst *AI,
356 const SCEV *AccessSize) {
360 if (isa<SCEVCouldNotCompute>(AccessSize))
363 const auto *
I = cast<Instruction>(
U.getUser());
365 auto ToCharPtr = [&](
const SCEV *
V) {
366 auto *PtrTy = IntegerType::getInt8PtrTy(SE.getContext());
367 return SE.getTruncateOrZeroExtend(V, PtrTy);
370 const SCEV *AddrExp = ToCharPtr(SE.getSCEV(
U.get()));
371 const SCEV *BaseExp = ToCharPtr(SE.getSCEV(AI));
372 const SCEV *Diff = SE.getMinusSCEV(AddrExp, BaseExp);
373 if (isa<SCEVCouldNotCompute>(Diff))
376 auto Size = getStaticAllocaSizeRange(*AI);
378 auto *CalculationTy = IntegerType::getIntNTy(SE.getContext(), PointerSize);
379 auto ToDiffTy = [&](
const SCEV *
V) {
380 return SE.getTruncateOrZeroExtend(V, CalculationTy);
382 const SCEV *Min = ToDiffTy(SE.getConstant(
Size.getLower()));
383 const SCEV *
Max = SE.getMinusSCEV(ToDiffTy(SE.getConstant(
Size.getUpper())),
384 ToDiffTy(AccessSize));
385 return SE.evaluatePredicateAt(ICmpInst::Predicate::ICMP_SGE, Diff, Min,
I)
387 SE.evaluatePredicateAt(ICmpInst::Predicate::ICMP_SLE, Diff, Max,
I)
393void StackSafetyLocalAnalysis::analyzeAllUses(
Value *
Ptr,
394 UseInfo<GlobalValue> &US,
402 while (!WorkList.
empty()) {
404 for (
const Use &UI :
V->uses()) {
405 const auto *
I = cast<Instruction>(UI.getUser());
411 switch (
I->getOpcode()) {
412 case Instruction::Load: {
414 US.addRange(
I, UnknownRange,
false);
418 auto AccessRange = getAccessRange(UI,
Ptr,
TypeSize);
419 bool Safe = isSafeAccess(UI, AI,
TypeSize);
420 US.addRange(
I, AccessRange, Safe);
424 case Instruction::VAArg:
427 case Instruction::Store: {
428 if (V ==
I->getOperand(0)) {
430 US.addRange(
I, UnknownRange,
false);
434 US.addRange(
I, UnknownRange,
false);
437 auto TypeSize =
DL.getTypeStoreSize(
I->getOperand(0)->getType());
438 auto AccessRange = getAccessRange(UI,
Ptr,
TypeSize);
439 bool Safe = isSafeAccess(UI, AI,
TypeSize);
440 US.addRange(
I, AccessRange, Safe);
444 case Instruction::Ret:
448 US.addRange(
I, UnknownRange,
false);
451 case Instruction::Call:
452 case Instruction::Invoke: {
453 if (
I->isLifetimeStartOrEnd())
457 US.addRange(
I, UnknownRange,
false);
461 auto AccessRange = getMemIntrinsicAccessRange(
MI, UI,
Ptr);
463 if (
const auto *MTI = dyn_cast<MemTransferInst>(
MI)) {
464 if (MTI->getRawSource() != UI && MTI->getRawDest() != UI)
466 }
else if (
MI->getRawDest() != UI) {
469 Safe = Safe || isSafeAccess(UI, AI,
MI->getLength());
470 US.addRange(
I, AccessRange, Safe);
474 const auto &CB = cast<CallBase>(*
I);
475 if (CB.getReturnedArgOperand() == V) {
477 WorkList.
push_back(cast<const Instruction>(
I));
480 if (!CB.isArgOperand(&UI)) {
481 US.addRange(
I, UnknownRange,
false);
485 unsigned ArgNo = CB.getArgOperandNo(&UI);
486 if (CB.isByValArgument(ArgNo)) {
487 auto TypeSize =
DL.getTypeStoreSize(CB.getParamByValType(ArgNo));
488 auto AccessRange = getAccessRange(UI,
Ptr,
TypeSize);
489 bool Safe = isSafeAccess(UI, AI,
TypeSize);
490 US.addRange(
I, AccessRange, Safe);
498 dyn_cast<GlobalValue>(CB.getCalledOperand()->stripPointerCasts());
500 US.addRange(
I, UnknownRange,
false);
509 Insert.first->second =
Insert.first->second.unionWith(Offsets);
515 WorkList.
push_back(cast<const Instruction>(
I));
521FunctionInfo<GlobalValue> StackSafetyLocalAnalysis::run() {
522 FunctionInfo<GlobalValue>
Info;
524 "Can't run StackSafety on a function declaration");
530 if (
auto *AI = dyn_cast<AllocaInst>(&
I))
535 for (
auto *AI : Allocas) {
536 auto &UI =
Info.Allocas.emplace(AI, PointerSize).first->second;
537 analyzeAllUses(AI, UI, SL);
543 if (
A.getType()->isPointerTy() && !
A.hasByValAttr()) {
544 auto &UI =
Info.Params.emplace(
A.getArgNo(), PointerSize).first->second;
545 analyzeAllUses(&
A, UI, SL);
554template <
typename CalleeTy>
class StackSafetyDataFlowAnalysis {
555 using FunctionMap = std::map<const CalleeTy *, FunctionInfo<CalleeTy>>;
557 FunctionMap Functions;
564 bool updateOneUse(UseInfo<CalleeTy> &US,
bool UpdateToFullSet);
565 void updateOneNode(
const CalleeTy *
Callee, FunctionInfo<CalleeTy> &FS);
566 void updateOneNode(
const CalleeTy *
Callee) {
569 void updateAllNodes() {
570 for (
auto &
F : Functions)
571 updateOneNode(
F.first,
F.second);
575 void verifyFixedPoint();
579 StackSafetyDataFlowAnalysis(
uint32_t PointerBitWidth, FunctionMap Functions)
580 : Functions(
std::
move(Functions)),
583 const FunctionMap &
run();
589template <
typename CalleeTy>
590ConstantRange StackSafetyDataFlowAnalysis<CalleeTy>::getArgumentAccessRange(
591 const CalleeTy *
Callee,
unsigned ParamNo,
593 auto FnIt = Functions.find(
Callee);
595 if (FnIt == Functions.end())
597 auto &
FS = FnIt->second;
598 auto ParamIt =
FS.Params.find(ParamNo);
599 if (ParamIt ==
FS.Params.end())
601 auto &Access = ParamIt->second.Range;
602 if (Access.isEmptySet())
604 if (Access.isFullSet())
606 return addOverflowNever(Access, Offsets);
609template <
typename CalleeTy>
610bool StackSafetyDataFlowAnalysis<CalleeTy>::updateOneUse(UseInfo<CalleeTy> &US,
611 bool UpdateToFullSet) {
612 bool Changed =
false;
613 for (
auto &KV : US.Calls) {
614 assert(!KV.second.isEmptySet() &&
615 "Param range can't be empty-set, invalid offset range");
618 getArgumentAccessRange(KV.first.Callee, KV.first.ParamNo, KV.second);
619 if (!US.Range.contains(CalleeRange)) {
622 US.Range = UnknownRange;
624 US.updateRange(CalleeRange);
630template <
typename CalleeTy>
631void StackSafetyDataFlowAnalysis<CalleeTy>::updateOneNode(
632 const CalleeTy *
Callee, FunctionInfo<CalleeTy> &FS) {
634 bool Changed =
false;
635 for (
auto &KV :
FS.Params)
636 Changed |= updateOneUse(KV.second, UpdateToFullSet);
640 << (UpdateToFullSet ?
", full-set" :
"") <<
"] " << &FS
643 for (
auto &CallerID : Callers[
Callee])
644 WorkList.
insert(CallerID);
650template <
typename CalleeTy>
651void StackSafetyDataFlowAnalysis<CalleeTy>::runDataFlow() {
653 for (
auto &
F : Functions) {
656 for (
auto &KV :
FS.Params)
657 for (
auto &CS : KV.second.Calls)
663 for (
auto &
Callee : Callees)
664 Callers[
Callee].push_back(
F.first);
669 while (!WorkList.
empty()) {
676template <
typename CalleeTy>
677void StackSafetyDataFlowAnalysis<CalleeTy>::verifyFixedPoint() {
684template <
typename CalleeTy>
685const typename StackSafetyDataFlowAnalysis<CalleeTy>::FunctionMap &
686StackSafetyDataFlowAnalysis<CalleeTy>::run() {
695 auto SummaryList =
VI.getSummaryList();
697 for (
const auto& GVS : SummaryList) {
700 if (
const AliasSummary *AS = dyn_cast<AliasSummary>(GVS.get()))
701 if (!AS->hasAliasee())
703 if (!isa<FunctionSummary>(GVS->getBaseObject()))
706 if (GVS->modulePath() == ModuleId) {
712 ++NumIndexCalleeMultipleExternal;
718 ++NumIndexCalleeMultipleWeak;
724 if (SummaryList.size() == 1)
728 ++NumIndexCalleeUnhandled;
750 if (
const Function *
F = dyn_cast<Function>(GV))
755 GV =
A->getAliaseeObject();
766 for (
const auto &PS :
FS.paramAccesses())
767 if (ParamNo == PS.ParamNo)
772void resolveAllCalls(UseInfo<GlobalValue> &
Use,
777 UseInfo<GlobalValue>::CallsTy TmpCalls;
779 for (
const auto &
C : TmpCalls) {
780 const Function *
F = findCalleeInModule(
C.first.Callee);
787 return Use.updateRange(FullSet);
789 findCalleeFunctionSummary(
Index->getValueInfo(
C.first.Callee->getGUID()),
790 C.first.Callee->getParent()->getModuleIdentifier());
791 ++NumModuleCalleeLookupTotal;
793 ++NumModuleCalleeLookupFailed;
794 return Use.updateRange(FullSet);
796 const ConstantRange *Found = findParamAccess(*FS,
C.first.ParamNo);
798 return Use.updateRange(FullSet);
801 Use.updateRange(addOverflowNever(Access,
C.second));
805GVToSSI createGlobalStackSafetyInfo(
806 std::map<
const GlobalValue *, FunctionInfo<GlobalValue>> Functions,
809 if (Functions.empty())
813 auto Copy = Functions;
815 for (
auto &FnKV : Copy)
816 for (
auto &KV : FnKV.second.Params) {
817 resolveAllCalls(KV.second,
Index);
818 if (KV.second.Range.isFullSet())
819 KV.second.Calls.clear();
823 Copy.begin()->first->getParent()->getDataLayout().getPointerSizeInBits();
824 StackSafetyDataFlowAnalysis<GlobalValue> SSDFA(PointerSize, std::move(Copy));
826 for (
const auto &
F : SSDFA.run()) {
828 auto &SrcF = Functions[
F.first];
829 for (
auto &KV : FI.Allocas) {
831 resolveAllCalls(
A,
Index);
832 for (
auto &
C :
A.Calls) {
833 A.updateRange(SSDFA.getArgumentAccessRange(
C.first.Callee,
834 C.first.ParamNo,
C.second));
837 A.Calls = SrcF.Allocas.find(KV.first)->second.Calls;
839 for (
auto &KV : FI.Params) {
841 P.Calls = SrcF.Params.find(KV.first)->second.Calls;
843 SSI[
F.first] = std::move(FI);
855 :
F(
F), GetSE(GetSE) {}
865 StackSafetyLocalAnalysis SSLA(*
F, GetSE());
872 getInfo().
Info.print(O,
F->getName(), dyn_cast<Function>(
F));
878 std::map<const GlobalValue *, FunctionInfo<GlobalValue>> Functions;
880 if (!
F.isDeclaration()) {
881 auto FI = GetSSI(
F).getInfo().Info;
882 Functions.emplace(&
F, std::move(FI));
885 Info.reset(
new InfoTy{
886 createGlobalStackSafetyInfo(std::move(Functions),
Index), {}, {}});
888 for (
auto &FnKV :
Info->Info) {
889 for (
auto &KV : FnKV.second.Allocas) {
892 auto AIRange = getStaticAllocaSizeRange(*AI);
893 if (AIRange.contains(KV.second.Range)) {
894 Info->SafeAllocas.insert(AI);
895 ++NumAllocaStackSafe;
897 Info->UnsafeAccesses.insert(KV.second.UnsafeAccesses.begin(),
898 KV.second.UnsafeAccesses.end());
908std::vector<FunctionSummary::ParamAccess>
912 std::vector<FunctionSummary::ParamAccess> ParamAccesses;
914 auto &PS = KV.second;
918 if (PS.Range.isFullSet())
921 ParamAccesses.emplace_back(KV.first, PS.Range);
924 Param.Calls.reserve(PS.Calls.size());
925 for (
const auto &
C : PS.Calls) {
930 if (
C.second.isFullSet()) {
931 ParamAccesses.pop_back();
934 Param.Calls.emplace_back(
C.first.ParamNo,
935 Index.getOrInsertValueInfo(
C.first.Callee),
942 return std::tie(L.ParamNo, L.Callee) < std::tie(R.ParamNo, R.Callee);
945 return ParamAccesses;
967 const auto &
Info = getInfo();
968 return Info.SafeAllocas.count(&AI);
972 const auto &
Info = getInfo();
973 return Info.UnsafeAccesses.find(&
I) ==
Info.UnsafeAccesses.end();
977 auto &SSI = getInfo().
Info;
980 const Module &M = *SSI.begin()->first->getParent();
981 for (
const auto &
F : M.functions()) {
982 if (!
F.isDeclaration()) {
983 SSI.find(&
F)->second.print(O,
F.getName(), &
F);
984 O <<
" safe accesses:"
987 const CallInst *Call = dyn_cast<CallInst>(&
I);
988 if ((isa<StoreInst>(
I) || isa<LoadInst>(
I) || isa<MemIntrinsic>(
I) ||
989 (Call && Call->hasByValArgument())) &&
991 O <<
" " <<
I <<
"\n";
1012 OS <<
"'Stack Safety Local Analysis' for function '" <<
F.getName() <<
"'\n";
1033 auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
1054 OS <<
"'Stack Safety Analysis' for module '" << M.getName() <<
"'\n";
1082 if (
auto *IndexWrapperPass =
1083 getAnalysisIfAvailable<ImmutableModuleSummaryIndexWrapperPass>())
1084 ImportSummary = IndexWrapperPass->getIndex();
1088 return getAnalysis<StackSafetyInfoWrapperPass>(
F).getResult();
1097 for (
const auto &
F : M.functions())
1098 if (
F.hasFnAttribute(Attribute::SanitizeMemTag))
1104 if (!
Index.hasParamAccess())
1108 auto CountParamAccesses = [&](
auto &Stat) {
1111 for (
auto &GVS :
Index)
1112 for (
auto &GV : GVS.second.SummaryList)
1114 Stat += FS->paramAccesses().size();
1117 CountParamAccesses(NumCombinedParamAccessesBefore);
1119 std::map<const FunctionSummary *, FunctionInfo<FunctionSummary>> Functions;
1122 for (
auto &GVS :
Index) {
1123 for (
auto &GV : GVS.second.SummaryList) {
1125 if (!FS || FS->paramAccesses().empty())
1127 if (FS->isLive() && FS->isDSOLocal()) {
1128 FunctionInfo<FunctionSummary> FI;
1129 for (
const auto &PS : FS->paramAccesses()) {
1135 for (
const auto &Call : PS.Calls) {
1136 assert(!Call.Offsets.isFullSet());
1138 findCalleeFunctionSummary(Call.Callee, FS->modulePath());
1139 ++NumCombinedCalleeLookupTotal;
1141 ++NumCombinedCalleeLookupFailed;
1150 Functions.emplace(FS, std::move(FI));
1155 FS->setParamAccesses({});
1158 NumCombinedDataFlowNodes += Functions.size();
1159 StackSafetyDataFlowAnalysis<FunctionSummary> SSDFA(
1161 for (
const auto &KV : SSDFA.run()) {
1162 std::vector<FunctionSummary::ParamAccess> NewParams;
1163 NewParams.reserve(KV.second.Params.size());
1164 for (
const auto &Param : KV.second.Params) {
1166 if (Param.second.Range.isFullSet())
1168 NewParams.emplace_back();
1170 New.ParamNo = Param.first;
1171 New.Use = Param.second.Range;
1174 std::move(NewParams));
1177 CountParamAccesses(NumCombinedParamAccessesAfter);
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
amdgpu Simplify well known AMD library false FunctionCallee Callee
This file implements a class to represent arbitrary precision integral constant values and operations...
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
block Block Frequency Analysis
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Analysis containing CSE Info
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This is the interface to build a ModuleSummaryIndex for a module.
ModuleSummaryIndex.h This file contains the declarations the classes that hold the module index and s...
print must be executed print the must be executed context for all instructions
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
static const char LocalPassArg[]
static const char LocalPassName[]
static true const char GlobalPassName[]
static cl::opt< int > StackSafetyMaxIterations("stack-safety-max-iterations", cl::init(20), cl::Hidden)
static cl::opt< bool > StackSafetyRun("stack-safety-run", cl::init(false), cl::Hidden)
static cl::opt< bool > StackSafetyPrint("stack-safety-print", cl::init(false), cl::Hidden)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Class for arbitrary precision integers.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
Alias summary information.
an instruction to allocate memory on the stack
PointerType * getType() const
Overload to return most specific pointer type.
Type * getAllocatedType() const
Return the type that is being allocated by the instruction.
bool isArrayAllocation() const
Return true if there is an allocation size parameter to the allocation instruction that is not 1.
const Value * getArraySize() const
Get the number of elements allocated.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
void setPreservesAll()
Set by analyses that do not transform their input at all.
AnalysisUsage & addRequiredTransitive()
This class represents an incoming formal argument to a Function.
This class represents a function call, abstracting a target machine's calling convention.
This class represents a range of values.
bool isFullSet() const
Return true if this set contains all of the elements possible for this data-type.
bool isEmptySet() const
Return true if this set contains no members.
ConstantRange sextOrTrunc(uint32_t BitWidth) const
Make this range have the bit width given by BitWidth.
A parsed version of the target data layout string in and methods for querying it.
FunctionPass class - This class is used to implement most global optimizations.
Function summary information to aid decisions and implementation of importing.
Function and variable summary information to aid decisions and implementation of importing.
GlobalValueSummary * getBaseObject()
If this is an alias summary, returns the summary of the aliased object (a global variable or function...
static bool isLocalLinkage(LinkageTypes Linkage)
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
static bool isLinkOnceLinkage(LinkageTypes Linkage)
static bool isAvailableExternallyLinkage(LinkageTypes Linkage)
static bool isExternalLinkage(LinkageTypes Linkage)
bool isInterposable() const
Return true if this global's definition can be substituted with an arbitrary definition at link time ...
static bool isWeakLinkage(LinkageTypes Linkage)
Legacy wrapper pass to provide the ModuleSummaryIndex object.
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
This is the common base class for memset/memcpy/memmove.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Class to hold module path string table and global value map, and encapsulate methods for operating on...
A Module instance is used to store all the information related to an LLVM module.
iterator_range< iterator > functions()
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
This class represents an analyzed expression in the program.
Analysis pass that exposes the ScalarEvolution for a function.
The main scalar evolution driver.
A vector that has set insertion semantics.
bool insert(const value_type &X)
Insert a new element into the SetVector.
void clear()
Completely clear the SetVector.
bool empty() const
Determine if the SetVector is empty or not.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
iterator erase(const_iterator CI)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Compute live ranges of allocas.
bool isReachable(const Instruction *I) const
Returns true if instruction is reachable from entry.
bool isAliveAfter(const AllocaInst *AI, const Instruction *I) const
Returns true if the alloca is alive after the instruction.
StackSafetyInfo wrapper for the new pass manager.
StackSafetyInfo run(Function &F, FunctionAnalysisManager &AM)
This pass performs the global (interprocedural) stack safety analysis (new pass manager).
Result run(Module &M, ModuleAnalysisManager &AM)
This pass performs the global (interprocedural) stack safety analysis (legacy pass manager).
bool runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
StackSafetyGlobalInfoWrapperPass()
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
void print(raw_ostream &O, const Module *M) const override
print - Print out the internal state of the pass.
~StackSafetyGlobalInfoWrapperPass()
void print(raw_ostream &O) const
bool stackAccessIsSafe(const Instruction &I) const
bool isSafe(const AllocaInst &AI) const
StackSafetyGlobalInfo & operator=(StackSafetyGlobalInfo &&)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
StackSafetyInfo wrapper for the legacy pass manager.
void print(raw_ostream &O, const Module *M) const override
print - Print out the internal state of the pass.
bool runOnFunction(Function &F) override
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
StackSafetyInfoWrapperPass()
Interface to access stack safety analysis results for single function.
void print(raw_ostream &O) const
const InfoTy & getInfo() const
StackSafetyInfo & operator=(StackSafetyInfo &&)
std::vector< FunctionSummary::ParamAccess > getParamAccesses(ModuleSummaryIndex &Index) const
Parameters use for a FunctionSummary.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
StringRef - Represent a constant reference to a string, i.e.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
StringRef getName() const
Return a constant reference to the value's name.
constexpr ScalarTy getFixedValue() const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
This class implements an extremely fast bulk output stream that can only output to a stream.
@ C
The default llvm calling convention, compatible with C.
initializer< Ty > init(const Ty &Val)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
constexpr uint64_t PointerSize
aarch64 pointer size.
This is an optimization pass for GlobalISel generic memory operations.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
void generateParamAccessSummary(ModuleSummaryIndex &Index)
bool needsParamAccessSummary(const Module &M)
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr)
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool AreStatisticsEnabled()
Check if statistics are enabled.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void initializeStackSafetyGlobalInfoWrapperPassPass(PassRegistry &)
void initializeStackSafetyInfoWrapperPassPass(PassRegistry &)
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
std::set< const Instruction * > UnsafeAccesses
SmallPtrSet< const AllocaInst *, 8 > SafeAllocas
FunctionInfo< GlobalValue > Info
A special type used by analysis passes to provide an address that identifies that particular analysis...
Describes the use of a value in a call instruction, specifying the call's target, the value's paramet...
Describes the uses of a parameter by the function.
static constexpr uint32_t RangeWidth
Struct that holds a reference to a particular GUID in a global value summary.