diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h --- a/llvm/include/llvm/Transforms/IPO/Attributor.h +++ b/llvm/include/llvm/Transforms/IPO/Attributor.h @@ -125,12 +125,12 @@ namespace llvm { struct AADepGraphNode; +struct AACallGraphNode; struct AADepGraph; struct Attributor; struct AbstractAttribute; struct InformationCache; struct AAIsDead; -struct AttributorCallGraph; struct IRPosition; class AAManager; @@ -216,6 +216,13 @@ bool canBeAssumedDead(Attributor &A, const Function &F, const AbstractAttribute &QueryingAA); +/// Return true if \p ToI is potentially reachable from \p FromI. The two +/// instructions do not need to be in the same function. +bool isPotentiallyReachable( + Attributor &A, const Instruction &FromI, const Instruction &ToI, + const AbstractAttribute &QueryingAA, + function_ref GoBackwardsCB = nullptr); + } // namespace AA /// The value passed to the line option that defines the maximal initialization @@ -1805,6 +1812,19 @@ bool RequireAllCallSites, bool &AllCallSitesKnown, bool VisitDeadCallSites = false); + /// Check \p Pred on all call sites of \p Fn. + /// + /// This method will evaluate \p Pred on call sites and return + /// true if \p Pred holds in every call sites. However, this is only possible + /// all call sites are known, hence the function has internal linkage. + /// If true is returned, \p AllCallSitesKnown is set if all possible call + /// sites of the function have been visited. + bool checkForAllCallSites(function_ref Pred, + const Function &Fn, bool RequireAllCallSites, + const AbstractAttribute *QueryingAA, + bool &AllCallSitesKnown, + bool VisitDeadCallSites = false); + /// Check \p Pred on all values potentially returned by \p F. /// /// This method will evaluate \p Pred on all values potentially returned by @@ -1943,19 +1963,6 @@ /// may trigger further updates. (\see DependenceStack) void rememberDependences(); - /// Check \p Pred on all call sites of \p Fn. - /// - /// This method will evaluate \p Pred on call sites and return - /// true if \p Pred holds in every call sites. However, this is only possible - /// all call sites are known, hence the function has internal linkage. - /// If true is returned, \p AllCallSitesKnown is set if all possible call - /// sites of the function have been visited. - bool checkForAllCallSites(function_ref Pred, - const Function &Fn, bool RequireAllCallSites, - const AbstractAttribute *QueryingAA, - bool &AllCallSitesKnown, - bool VisitDeadCallSites = false); - /// Determine if CallBase context in \p IRP should be propagated. bool shouldPropagateCallBaseContext(const IRPosition &IRP); @@ -2072,7 +2079,7 @@ const char *PassName = ""; friend AADepGraph; - friend AttributorCallGraph; + friend AACallGraphNode; }; /// An interface to query the internal state of an abstract attribute. @@ -4275,84 +4282,62 @@ static const char ID; }; -struct AACallGraphNode; -struct AACallEdges; - -/// An Iterator for call edges, creates AACallEdges attributes in a lazy way. -/// This iterator becomes invalid if the underlying edge list changes. -/// So This shouldn't outlive a iteration of Attributor. -class AACallEdgeIterator - : public iterator_adaptor_base::iterator> { - AACallEdgeIterator(Attributor &A, SetVector::iterator Begin) - : iterator_adaptor_base(Begin), A(A) {} - -public: - AACallGraphNode *operator*() const; - -private: - Attributor &A; - friend AACallEdges; - friend AttributorCallGraph; -}; - struct AACallGraphNode { - AACallGraphNode(Attributor &A) : A(A) {} + AACallGraphNode(Attributor &A); + AACallGraphNode(const Function &Fn); virtual ~AACallGraphNode() {} - virtual AACallEdgeIterator optimisticEdgesBegin() const = 0; - virtual AACallEdgeIterator optimisticEdgesEnd() const = 0; +protected: + void fillCallees(Attributor &A, + DenseMap &CGNodeMap); - /// Iterator range for exploring the call graph. - iterator_range optimisticEdgesRange() const { - return iterator_range(optimisticEdgesBegin(), - optimisticEdgesEnd()); - } + /// The associated function, or nullptr for the synthetic root. + const Function *Fn = nullptr; -protected: - /// Reference to Attributor needed for GraphTraits implementation. - Attributor &A; -}; + /// Container to hold the callees, filled by fillCallees. + std::vector Callees; -/// An abstract state for querying live call edges. -/// This interface uses the Attributor's optimistic liveness -/// information to compute the edges that are alive. -struct AACallEdges : public StateWrapper, - AACallGraphNode { - using Base = StateWrapper; +public: + using iterator = std::vector::const_iterator; - AACallEdges(const IRPosition &IRP, Attributor &A) - : Base(IRP), AACallGraphNode(A) {} + /// Iterator range for exploring the call graph. + iterator_range getCallEdgeIteratorRange() const { + return iterator_range(getCallEdgeIteratorBegin(), + getCallEdgeIteratorEnd()); + } - /// Get the optimistic edges. - virtual const SetVector &getOptimisticEdges() const = 0; + iterator getCallEdgeIteratorBegin() const { return Callees.begin(); } - /// Is there any call with a unknown callee. - virtual bool hasUnknownCallee() const = 0; + iterator getCallEdgeIteratorEnd() const { return Callees.end(); } - /// Is there any call with a unknown callee, excluding any inline asm. - virtual bool hasNonAsmUnknownCallee() const = 0; + void print(Attributor &A); - /// Iterator for exploring the call graph. - AACallEdgeIterator optimisticEdgesBegin() const override { - return AACallEdgeIterator(A, getOptimisticEdges().begin()); - } + std::string getName() const; +}; - /// Iterator for exploring the call graph. - AACallEdgeIterator optimisticEdgesEnd() const override { - return AACallEdgeIterator(A, getOptimisticEdges().end()); - } +struct AAExecutionDomain + : public StateWrapper { + using Base = StateWrapper; + AAExecutionDomain(const IRPosition &IRP, Attributor &A) : Base(IRP) {} /// Create an abstract attribute view for the position \p IRP. - static AACallEdges &createForPosition(const IRPosition &IRP, Attributor &A); + static AAExecutionDomain &createForPosition(const IRPosition &IRP, + Attributor &A); - /// See AbstractAttribute::getName() - const std::string getName() const override { return "AACallEdges"; } + /// See AbstractAttribute::getName(). + const std::string getName() const override { return "AAExecutionDomain"; } - /// See AbstractAttribute::getIdAddr() + /// See AbstractAttribute::getIdAddr(). const char *getIdAddr() const override { return &ID; } - /// This function should return true if the type of the \p AA is AACallEdges. + /// Check if an instruction is executed only by the initial thread. + virtual bool isExecutedByInitialThreadOnly(const Instruction &) const = 0; + + /// Check if a basic block is executed only by the initial thread. + virtual bool isExecutedByInitialThreadOnly(const BasicBlock &) const = 0; + + /// This function should return true if the type of the \p AA is + /// AAExecutionDomain. static bool classof(const AbstractAttribute *AA) { return (AA->getIdAddr() == &ID); } @@ -4361,101 +4346,94 @@ static const char ID; }; -// Synthetic root node for the Attributor's internal call graph. -struct AttributorCallGraph : public AACallGraphNode { - AttributorCallGraph(Attributor &A) : AACallGraphNode(A) {} - virtual ~AttributorCallGraph() {} - - AACallEdgeIterator optimisticEdgesBegin() const override { - return AACallEdgeIterator(A, A.Functions.begin()); +struct FunctionReachabilityState : public BooleanState { + void markReachable(const CallBase &FromCB, const Function &Fn) { + // We remember call site specific reachability and function wide + // reachability in the same set. + ReachableFns.insert({&FromCB, &Fn}); + ReachableFns.insert({nullptr, &Fn}); } - AACallEdgeIterator optimisticEdgesEnd() const override { - return AACallEdgeIterator(A, A.Functions.end()); + /// If we can reach a function with a call to a unknown function we assume + /// that we can reach any function. + bool canReachUnknownCallee() const { + return hasUnknownAsmCallee() || !isValidState(); } - /// Force populate the entire call graph. - void populateAll() const { - for (const AACallGraphNode *AA : optimisticEdgesRange()) { - // Nothing else to do here. - (void)AA; - } - } + /// Return true if we can reach an unknown callee via means other than inline + /// ASM. + bool canReachUnknownNonAsmCallee() const { return !isValidState(); } - void print(); -}; + /// Return true if we can reach an unknown callee via inline ASM. + bool hasUnknownAsmCallee() const { return HasUnknownAsmCallee; } -template <> struct GraphTraits { - using NodeRef = AACallGraphNode *; - using ChildIteratorType = AACallEdgeIterator; + void operator^=(const FunctionReachabilityState &Other) { + if (!Other.isValidState()) { + indicatePessimisticFixpoint(); + return; + } - static AACallEdgeIterator child_begin(AACallGraphNode *Node) { - return Node->optimisticEdgesBegin(); + ReachableFns.insert(Other.ReachableFns.begin(), Other.ReachableFns.end()); + HasUnknownAsmCallee |= Other.HasUnknownAsmCallee; } - static AACallEdgeIterator child_end(AACallGraphNode *Node) { - return Node->optimisticEdgesEnd(); + /// Return true if the associated function can reach \p Fn. + bool canPotentiallyReach(const Function &Fn) const { + return canReachUnknownCallee() || ReachableFns.contains({nullptr, &Fn}); } -}; -template <> -struct GraphTraits - : public GraphTraits { - using nodes_iterator = AACallEdgeIterator; - - static AACallGraphNode *getEntryNode(AttributorCallGraph *G) { - return static_cast(G); + /// Return true if the associated function can reach \p Fn through \p CB. + bool canPotentiallyReach(const CallBase &CB, const Function &Fn) const { + return canReachUnknownCallee() || ReachableFns.contains({&CB, &Fn}); } - static AACallEdgeIterator nodes_begin(const AttributorCallGraph *G) { - return G->optimisticEdgesBegin(); + /// Return a range of Function * that can be reached by this function. + auto getCallees() const { + return make_second_range( + make_filter_range(ReachableFns, [](auto &It) { return !It.first; })); } - static AACallEdgeIterator nodes_end(const AttributorCallGraph *G) { - return G->optimisticEdgesEnd(); + /// Return a range of Function * that can be reached via \p CB. + auto getCallees(const CallBase &CB) const { + return make_second_range(make_filter_range( + ReachableFns, [&](auto &It) { return It.first == &CB; })); } -}; - -template <> -struct DOTGraphTraits : public DefaultDOTGraphTraits { - DOTGraphTraits(bool Simple = false) : DefaultDOTGraphTraits(Simple) {} - std::string getNodeLabel(const AACallGraphNode *Node, - const AttributorCallGraph *Graph) { - const AACallEdges *AACE = static_cast(Node); - return AACE->getAssociatedFunction()->getName().str(); - } + /// Flag to indicate we have seen inline ASM that might have call-like + /// semantic. + bool HasUnknownAsmCallee = false; - static bool isNodeHidden(const AACallGraphNode *Node, - const AttributorCallGraph *Graph) { - // Hide the synth root. - return static_cast(Graph) == Node; - } + /// Set of functions that we know for sure is reachable attributed to the call + /// site that can reach them. + DenseSet> ReachableFns; }; -struct AAExecutionDomain - : public StateWrapper { - using Base = StateWrapper; - AAExecutionDomain(const IRPosition &IRP, Attributor &A) : Base(IRP) {} +/// An abstract Attribute for computing reachability between functions. +struct AAFunctionReachability + : public StateWrapper { + using Base = StateWrapper; - /// Create an abstract attribute view for the position \p IRP. - static AAExecutionDomain &createForPosition(const IRPosition &IRP, - Attributor &A); + AAFunctionReachability(const IRPosition &IRP, Attributor &A) : Base(IRP) {} - /// See AbstractAttribute::getName(). - const std::string getName() const override { return "AAExecutionDomain"; } + /// Can \p Inst potentially reach \p Fn. + virtual bool instructionCanPotentiallyReach(Attributor &A, + const Instruction &Inst, + const Function &Fn) const = 0; - /// See AbstractAttribute::getIdAddr(). - const char *getIdAddr() const override { return &ID; } + /// Create an abstract attribute view for the position \p IRP. + static AAFunctionReachability &createForPosition(const IRPosition &IRP, + Attributor &A); - /// Check if an instruction is executed only by the initial thread. - virtual bool isExecutedByInitialThreadOnly(const Instruction &) const = 0; + /// See AbstractAttribute::getName() + const std::string getName() const override { + return "AAFunctionReachability"; + } - /// Check if a basic block is executed only by the initial thread. - virtual bool isExecutedByInitialThreadOnly(const BasicBlock &) const = 0; + /// See AbstractAttribute::getIdAddr() + const char *getIdAddr() const override { return &ID; } /// This function should return true if the type of the \p AA is - /// AAExecutionDomain. + /// AAFunctionReachability. static bool classof(const AbstractAttribute *AA) { return (AA->getIdAddr() == &ID); } @@ -4464,44 +4442,46 @@ static const char ID; }; -/// An abstract Attribute for computing reachability between functions. -struct AAFunctionReachability - : public StateWrapper { - using Base = StateWrapper; - - AAFunctionReachability(const IRPosition &IRP, Attributor &A) : Base(IRP) {} +template <> struct GraphTraits { + using NodeRef = const AACallGraphNode *; + using ChildIteratorType = AACallGraphNode::iterator; + using nodes_iterator = AACallGraphNode::iterator; - /// If the function represented by this possition can reach \p Fn. - virtual bool canReach(Attributor &A, Function &Fn) const = 0; + static const AACallGraphNode *getEntryNode(const AACallGraphNode *G) { + return G; + } - /// Can \p CB reach \p Fn - virtual bool canReach(Attributor &A, CallBase &CB, Function &Fn) const = 0; + static nodes_iterator nodes_begin(const AACallGraphNode *G) { + return child_begin(G); + } - /// Can \p Inst reach \p Fn - virtual bool instructionCanReach(Attributor &A, Instruction &Inst, - Function &Fn, - bool UseBackwards = true) const = 0; + static nodes_iterator nodes_end(const AACallGraphNode *G) { + return child_end(G); + } - /// Create an abstract attribute view for the position \p IRP. - static AAFunctionReachability &createForPosition(const IRPosition &IRP, - Attributor &A); + static nodes_iterator child_begin(const AACallGraphNode *Node) { + return Node->getCallEdgeIteratorBegin(); + } - /// See AbstractAttribute::getName() - const std::string getName() const override { return "AAFuncitonReacability"; } + static nodes_iterator child_end(const AACallGraphNode *Node) { + return Node->getCallEdgeIteratorEnd(); + } +}; - /// See AbstractAttribute::getIdAddr() - const char *getIdAddr() const override { return &ID; } +template <> +struct DOTGraphTraits : public DefaultDOTGraphTraits { + DOTGraphTraits(bool Simple = false) : DefaultDOTGraphTraits(Simple) {} - /// This function should return true if the type of the \p AA is AACallEdges. - static bool classof(const AbstractAttribute *AA) { - return (AA->getIdAddr() == &ID); + std::string getNodeLabel(const AACallGraphNode *Node, + const AACallGraphNode *Graph) { + return Node->getName(); } - /// Unique ID (due to the unique address) - static const char ID; -private: - /// Can this function reach a call with unknown calee. - virtual bool canReachUnknownCallee() const = 0; + static bool isNodeHidden(const AACallGraphNode *Node, + const AACallGraphNode *Graph) { + // Hide the synth root. + return Node->getName() == Graph->getName(); + } }; /// An abstract interface for struct information. diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAttributor.cpp b/llvm/lib/Target/AMDGPU/AMDGPUAttributor.cpp --- a/llvm/lib/Target/AMDGPU/AMDGPUAttributor.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUAttributor.cpp @@ -345,9 +345,9 @@ auto OrigAssumed = getAssumed(); // Check for Intrinsics and propagate attributes. - const AACallEdges &AAEdges = A.getAAFor( + const auto &FunctionReachabilityAA = A.getAAFor( *this, this->getIRPosition(), DepClassTy::REQUIRED); - if (AAEdges.hasNonAsmUnknownCallee()) + if (FunctionReachabilityAA.canReachUnknownNonAsmCallee()) return indicatePessimisticFixpoint(); bool IsNonEntryFunc = !AMDGPU::isEntryFunctionCC(F->getCallingConv()); @@ -355,7 +355,7 @@ bool NeedsQueuePtr = false; - for (Function *Callee : AAEdges.getOptimisticEdges()) { + for (const Function *Callee : FunctionReachabilityAA.getCallees()) { Intrinsic::ID IID = Callee->getIntrinsicID(); if (IID == Intrinsic::not_intrinsic) { const AAAMDAttributes &AAAMD = A.getAAFor( @@ -493,7 +493,7 @@ BumpPtrAllocator Allocator; AMDGPUInformationCache InfoCache(M, AG, Allocator, nullptr, *TM); DenseSet Allowed( - {&AAAMDAttributes::ID, &AAAMDWorkGroupSize::ID, &AACallEdges::ID}); + {&AAAMDAttributes::ID, &AAAMDWorkGroupSize::ID, &AAFunctionReachability::ID}); Attributor A(Functions, InfoCache, CGUpdater, &Allowed); diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/TinyPtrVector.h" #include "llvm/Analysis/InlineCost.h" @@ -438,6 +439,97 @@ }); } +bool AA::isPotentiallyReachable( + Attributor &A, const Instruction &FromI, const Instruction &ToI, + const AbstractAttribute &QueryingAA, + function_ref GoBackwardsCB) { + LLVM_DEBUG(dbgs() << "[AA] isPotentiallyReachable " << ToI << " from " + << FromI << " [GBCB: " << bool(GoBackwardsCB) << "]\n"); + + SmallPtrSet Visited; + SmallVector Worklist; + Worklist.push_back(&FromI); + + while (!Worklist.empty()) { + const Instruction *CurFromI = Worklist.pop_back_val(); + if (!Visited.insert(CurFromI).second) + continue; + + const Function *ToFn = ToI.getFunction(); + const Function *FromFn = CurFromI->getFunction(); + if (FromFn == ToFn) { + LLVM_DEBUG(dbgs() << "[AA] check " << ToI << " from " << *CurFromI + << " intraprocedurally\n"); + const auto &ReachabilityAA = A.getAAFor( + QueryingAA, IRPosition::function(*ToFn), DepClassTy::OPTIONAL); + bool Result = ReachabilityAA.isAssumedReachable(A, *CurFromI, ToI); + LLVM_DEBUG(dbgs() << "[AA] " << *CurFromI << " " + << (Result ? "can potentially " : "cannot ") << "reach " + << ToI << " [Intra]\n"); + if (Result) + return true; + continue; + } + + // If we can go arbitrarily backwards we will eventually reach an entry + // point that can reach ToI. Only once this takes a set of blocks through + // which we cannot go it makes sense to perform analysis in the absence of a + // GoBackwardsCB. + if (!GoBackwardsCB) { + LLVM_DEBUG(dbgs() << "[AA] check " << ToI << " from " << *CurFromI + << " is not checked backwards, give up\n"); + return true; + } + + // Check if the FromFn is already known to reach the ToFn. + const auto &FnReachabilityAA = A.getAAFor( + QueryingAA, IRPosition::function(*FromFn), DepClassTy::OPTIONAL); + bool Result = + FnReachabilityAA.instructionCanPotentiallyReach(A, *CurFromI, *ToFn); + LLVM_DEBUG(dbgs() << "[AA] " << *CurFromI << " " + << (Result ? "can potentially " : "cannot ") << "reach " + << ToFn->getName() << " [FromFn]\n"); + if (Result) + return true; + + // If we do not go backwards from the FromFn we are done here and so far we + // could not find a way to reach ToI. + if (!GoBackwardsCB(*FromFn)) + continue; + + LLVM_DEBUG(dbgs() << "Stepping backwards to the call sites of " + << FromFn->getName() << "\n"); + + auto CheckCallSite = [&](AbstractCallSite ACS) { + CallBase *CB = ACS.getInstruction(); + if (!CB) + return false; + + if (isa(CB)) + return false; + + Instruction *Inst = CB->getNextNonDebugInstruction(); + Worklist.push_back(Inst); + return true; + }; + + bool AllCallSitesKnown; + Result = !A.checkForAllCallSites(CheckCallSite, *FromFn, + /* RequireAllCallSites */ true, + &QueryingAA, AllCallSitesKnown); + if (Result) { + LLVM_DEBUG(dbgs() << "[AA] stepping back to call sites from " << *CurFromI + << " in " << FromFn->getName() << " failed, give up\n"); + return true; + } + + LLVM_DEBUG(dbgs() << "[AA] stepped back to call sites from " << *CurFromI + << " in " << FromFn->getName() + << " worklist size is: " << Worklist.size() << "\n"); + } + return false; +} + /// Return true if \p New is equal or worse than \p Old. static bool isEqualOrWorse(const Attribute &New, const Attribute &Old) { if (!Old.isIntAttribute()) @@ -1931,10 +2023,10 @@ ChangeStatus Attributor::run() { TimeTraceScope TimeScope("Attributor::run"); - AttributorCallGraph ACallGraph(*this); + AACallGraphNode *ACallGraph = nullptr; if (PrintCallGraph) - ACallGraph.populateAll(); + ACallGraph = new (Allocator) AACallGraphNode(*this); Phase = AttributorPhase::UPDATE; runTillFixpoint(); @@ -1949,15 +2041,15 @@ if (PrintDependencies) DG.print(); + if (PrintCallGraph) + ACallGraph->print(*this); + Phase = AttributorPhase::MANIFEST; ChangeStatus ManifestChange = manifestAttributes(); Phase = AttributorPhase::CLEANUP; ChangeStatus CleanupChange = cleanupIR(); - if (PrintCallGraph) - ACallGraph.print(); - return ManifestChange | CleanupChange; } @@ -2996,6 +3088,37 @@ cast(DepAA.getPointer())->printWithDeps(outs()); } +void AACallGraphNode::print(Attributor &A) { + Callees.reserve(A.Functions.size()); + DenseMap CGNodeMap; + for (const Function *Fn : A.Functions) { + Callees.push_back(new (A.Allocator) AACallGraphNode(*Fn)); + CGNodeMap[Fn] = Callees.back(); + } + for (auto *CGNode : Callees) + CGNode->fillCallees(A, CGNodeMap); + llvm::WriteGraph(outs(), this); +} + +AACallGraphNode::AACallGraphNode(Attributor &A) { + for (const Function *Fn : A.Functions) + A.getOrCreateAAFor(IRPosition::function(*Fn)); +} +AACallGraphNode::AACallGraphNode(const Function &Fn) : Fn(&Fn) {} + +void AACallGraphNode::fillCallees( + Attributor &A, DenseMap &CGNodeMap) { + Fn->dump(); + const auto &FRAA = + A.getOrCreateAAFor(IRPosition::function(*Fn)); + for (const Function *Fn : FRAA.getCallees()) + Callees.push_back(CGNodeMap[Fn]); +} + +std::string AACallGraphNode::getName() const { + return Fn ? Fn->getName().str() : ""; +} + PreservedAnalyses AttributorPass::run(Module &M, ModuleAnalysisManager &AM) { FunctionAnalysisManager &FAM = AM.getResult(M).getManager(); diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp --- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp +++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp @@ -32,6 +32,7 @@ #include "llvm/IR/Argument.h" #include "llvm/IR/Assumptions.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/GlobalValue.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" @@ -44,6 +45,7 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/IPO/ArgumentPromotion.h" +#include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Transforms/Utils/Local.h" #include @@ -152,7 +154,6 @@ PIPE_OPERATOR(AAUndefinedBehavior) PIPE_OPERATOR(AAPotentialValues) PIPE_OPERATOR(AANoUndef) -PIPE_OPERATOR(AACallEdges) PIPE_OPERATOR(AAFunctionReachability) PIPE_OPERATOR(AAPointerInfo) @@ -1123,25 +1124,6 @@ return CanIgnoreThreading(*Acc.getLocalInst()); }; - // Helper to determine if the instruction may reach the load. - auto IsReachableFrom = [&](const Instruction &I) { - if (I.getFunction() != LI.getFunction()) { - const auto &FnReachabilityAA = A.getAAFor( - QueryingAA, IRPosition::function(*I.getFunction()), - DepClassTy::OPTIONAL); - bool b = FnReachabilityAA.canReach(A, LI.getFunction()); - errs() << "QQQ " << I.getFunction()->getName() << " " << (b ? "can " : "cannot ") << "reach " << LI.getFunction()->getName()<<"\n"; - if (!b) - return false; - } - const auto &ReachabilityAA = A.getAAFor( - QueryingAA, IRPosition::function(*I.getFunction()), - DepClassTy::OPTIONAL); - bool b = ReachabilityAA.isAssumedReachable(A, I, LI); - errs() << I << " " << (b ? "can " : "cannot ") << "reach " << LI<<"\n"; - return b; - }; - const bool CanUseCFGResoning = CanIgnoreThreading(LI); LLVM_DEBUG(dbgs() << "Can use CFG reasoning: " << CanUseCFGResoning << "\n"); @@ -1149,6 +1131,58 @@ const DominatorTree *DT = InfoCache.getAnalysisResultForFunction(Scope); + enum GPUAddressSpace : unsigned { + Generic = 0, + Global = 1, + Shared = 3, + Constant = 4, + Local = 5, + }; + + // Helper to check if a value has "kernel lifetime", that is it will not + // outlive a GPU kernel. This is true for shared, constant, and local + // globals on AMD and NVIDIA GPUs. + auto HasKernelLifetime = [&](Value *V, Module &M) { + Triple T(M.getTargetTriple()); + if (!(T.isAMDGPU() || T.isNVPTX())) + return false; + switch (V->getType()->getPointerAddressSpace()) { + case GPUAddressSpace::Shared: + case GPUAddressSpace::Constant: + case GPUAddressSpace::Local: + return true; + default: + return false; + }; + }; + + // The IsLiveInCalleeCB will be used by the AA::isPotentiallyReachable query + // to determine if we should look at reachability from the callee. For + // certain pointers we know the lifetime and we do not have to step into the + // callee to determine reachability as the pointer would be dead in the + // callee. See the conditional initialization below. + function_ref IsLiveInCalleeCB = nullptr; + + if (auto *AI = dyn_cast(&getAssociatedValue())) { + // If the alloca containing function is not recursive the alloca + // must be dead in the callee. + const auto &NoRecurseAA = A.getAAFor( + *this, IRPosition::function(*AI->getFunction()), + DepClassTy::OPTIONAL); + if (NoRecurseAA.isAssumedNoRecurse()) { + IsLiveInCalleeCB = [=](const Function &Fn) { + return AI->getFunction() != &Fn; + }; + } + } else if (auto *GV = dyn_cast(&getAssociatedValue())) { + // If the global has kernel lifetime we can stop if we reach a kernel + // as it is "dead" in the (unknown) callees. + if (HasKernelLifetime(GV, *GV->getParent())) + IsLiveInCalleeCB = [=](const Function &Fn) { + return !Fn.hasFnAttribute("kernel"); + }; + } + auto AccessCB = [&](const Access &Acc, bool Exact) { if (!Acc.isWrite()) return true; @@ -1156,7 +1190,8 @@ // For now we only filter accesses based on CFG reasoning which does not // work yet if we have threading effects, or the access is complicated. if (CanUseCFGResoning) { - if (!IsReachableFrom(*Acc.getLocalInst())) + if (!AA::isPotentiallyReachable(A, *Acc.getLocalInst(), LI, QueryingAA, + IsLiveInCalleeCB)) return true; if (DT && Exact && (Acc.getLocalInst()->getFunction() == LI.getFunction()) && @@ -2462,16 +2497,6 @@ AANoRecurseFunction(const IRPosition &IRP, Attributor &A) : AANoRecurseImpl(IRP, A) {} - /// See AbstractAttribute::initialize(...). - void initialize(Attributor &A) override { - AANoRecurseImpl::initialize(A); - // TODO: We should build a call graph ourselves to enable this in the module - // pass as well. - if (const Function *F = getAnchorScope()) - if (A.getInfoCache().getSccSize(*F) != 1) - indicatePessimisticFixpoint(); - } - /// See AbstractAttribute::updateImpl(...). ChangeStatus updateImpl(Attributor &A) override { @@ -2494,6 +2519,12 @@ return ChangeStatus::UNCHANGED; } + // TODO: We should build a call graph ourselves to enable this in the module + // pass as well. + if (const Function *F = getAnchorScope()) + if (A.getInfoCache().getSccSize(*F) != 1) + indicatePessimisticFixpoint(); + // If the above check does not hold anymore we look at the calls. auto CheckForNoRecurse = [&](Instruction &I) { const auto &CB = cast(I); @@ -3808,7 +3839,6 @@ if (AssumedLiveBlocks.empty()) { A.deleteAfterManifest(F); - errs() << "delete after manifest!: " << F.getName() << "\n"; return ChangeStatus::CHANGED; } @@ -9486,71 +9516,131 @@ void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(noundef) } }; -struct AACallEdgesImpl : public AACallEdges { - AACallEdgesImpl(const IRPosition &IRP, Attributor &A) : AACallEdges(IRP, A) {} +struct AAFunctionReachabilityFunction : public AAFunctionReachability { - virtual const SetVector &getOptimisticEdges() const override { - return CalledFunctions; - } + AAFunctionReachabilityFunction(const IRPosition &IRP, Attributor &A) + : AAFunctionReachability(IRP, A) {} - virtual bool hasUnknownCallee() const override { return HasUnknownCallee; } + bool instructionCanPotentiallyReach(Attributor &A, const Instruction &Inst, + const Function &Fn) const override { + const auto &ReachAA = A.getAAFor( + *this, IRPosition::function(*getAssociatedFunction()), + DepClassTy::OPTIONAL); + if (!ReachAA.getState().isValidState()) { + LLVM_DEBUG( + dbgs() + << "[AAFuncReach] AAReachability is invalid, ignore context inst " + << Inst << "\n"); + return canPotentiallyReach(Fn); + } - virtual bool hasNonAsmUnknownCallee() const override { - return HasUnknownCalleeNonAsm; - } + // Determine call like instructions that we can reach from the inst. + auto CheckCallBase = [&](Instruction &CBInst) { + auto &CB = cast(CBInst); + bool CBCanReachInst = ReachAA.isAssumedReachable(A, Inst, CB); + LLVM_DEBUG(dbgs() << "[AAFuncReach] Isnt " << Inst + << (CBCanReachInst ? " can potentially " : " cannot ") + << "reach call base " << CB << "\n"); + if (!CBCanReachInst) + return true; + return !canPotentiallyReach(CB, Fn); + }; - const std::string getAsStr() const override { - return "CallEdges[" + std::to_string(HasUnknownCallee) + "," + - std::to_string(CalledFunctions.size()) + "]"; + bool UsedAssumedInformation = false; + if (!A.checkForAllCallLikeInstructions(CheckCallBase, *this, + UsedAssumedInformation)) + return true; + return false; } - void trackStatistics() const override {} + /// See AbstractAttribute::updateImpl(...). + ChangeStatus updateImpl(Attributor &A) override { + auto NumReachableBefore = ReachableFns.size(); + auto HasUnknownAsmCalleeBefore = HasUnknownAsmCallee; -protected: - void addCalledFunction(Function *Fn, ChangeStatus &Change) { - if (CalledFunctions.insert(Fn)) { - Change = ChangeStatus::CHANGED; - LLVM_DEBUG(dbgs() << "[AACallEdges] New call edge: " << Fn->getName() - << "\n"); - } - } + // Determine call like instructions that we can reach from the inst. + auto CheckCallBase = [&](Instruction &CBInst) { + auto &CB = cast(CBInst); + handleReachableCallBase(A, CB); + return getState().isValidState(); + }; - void setHasUnknownCallee(bool NonAsm, ChangeStatus &Change) { - if (!HasUnknownCallee) - Change = ChangeStatus::CHANGED; - if (NonAsm && !HasUnknownCalleeNonAsm) - Change = ChangeStatus::CHANGED; - HasUnknownCalleeNonAsm |= NonAsm; - HasUnknownCallee = true; + bool UsedAssumedInformation = false; + if (!A.checkForAllCallLikeInstructions(CheckCallBase, *this, + UsedAssumedInformation)) + return indicatePessimisticFixpoint(); + + if (!isValidState()) + return ChangeStatus::CHANGED; + + LLVM_DEBUG({ + dbgs() << "[AAFuncReach] Now reachable from " + << getAssociatedFunction()->getName() << ":\n"; + if (canReachUnknownNonAsmCallee()) + dbgs() << " - unknown non-asm callee\n"; + if (hasUnknownAsmCallee()) + dbgs() << " - unknown non-asm callee\n"; + for (auto *Fn : getCallees()) + dbgs() << " - " << Fn->getName() << "\n"; + }); + + return (NumReachableBefore == ReachableFns.size() && + HasUnknownAsmCalleeBefore == HasUnknownAsmCallee) + ? ChangeStatus::UNCHANGED + : ChangeStatus::CHANGED; } -private: - /// Optimistic set of functions that might be called by this position. - SetVector CalledFunctions; + const std::string getAsStr() const override { + if (canReachUnknownCallee()) + return "Reachable "; + return "Reachable Fns: #" + std::to_string(ReachableFns.size()) + + (hasUnknownAsmCallee() ? " and unknown asm callee" : ""); + } - /// Is there any call with a unknown callee. - bool HasUnknownCallee = false; + void trackStatistics() const override {} - /// Is there any call with a unknown callee, excluding any inline asm. - bool HasUnknownCalleeNonAsm = false; -}; +private: + /// Analyze the call base \p CB to determine reachable functions. + void handleReachableCallBase(Attributor &A, CallBase &CB) { + if (CB.isInlineAsm()) { + // Check if the assumptions tell us this is not a call. If not, record it + // as unknown asm call. + if (!hasAssumption(*CB.getCaller(), "ompx_no_call_asm") && + !hasAssumption(CB, "ompx_no_call_asm")) + HasUnknownAsmCallee = true; + return; + } -struct AACallEdgesCallSite : public AACallEdgesImpl { - AACallEdgesCallSite(const IRPosition &IRP, Attributor &A) - : AACallEdgesImpl(IRP, A) {} - /// See AbstractAttribute::updateImpl(...). - ChangeStatus updateImpl(Attributor &A) override { - ChangeStatus Change = ChangeStatus::UNCHANGED; + // Process callee metadata if available. + if (auto *MD = CB.getMetadata(LLVMContext::MD_callees)) { + for (auto &Op : MD->operands()) { + if (Function *Callee = mdconst::extract_or_null(Op)) { + LLVM_DEBUG(dbgs() + << "[AAFunctionReachability] Can reach via metadata " + << Callee->getName() << "\n"); + markReachable(CB, *Callee); + } else { + LLVM_DEBUG(dbgs() + << "[AAFunctionReachability] Invalid metadata metadata " + << *Op << "\n"); + indicatePessimisticFixpoint(); + } + } + return; + } auto VisitValue = [&](Value &V, const Instruction *CtxI, bool &HasUnknown, bool Stripped) -> bool { if (Function *Fn = dyn_cast(&V)) { - addCalledFunction(Fn, Change); + LLVM_DEBUG(dbgs() << "[AAFunctionReachability] Can reach " + << Fn->getName() << "\n"); + markReachable(CB, *Fn); } else { - LLVM_DEBUG(dbgs() << "[AACallEdges] Unrecognized value: " << V << "\n"); - setHasUnknownCallee(true, Change); + LLVM_DEBUG(dbgs() << "[AAFunctionReachability] Unrecognized value: " + << V << "\n"); + // Give up. + return false; } - // Explore all values. return true; }; @@ -9563,409 +9653,23 @@ false)) { // If we haven't gone through all values, assume that there are unknown // callees. - setHasUnknownCallee(true, Change); + indicatePessimisticFixpoint(); } }; - CallBase *CB = static_cast(getCtxI()); - - if (CB->isInlineAsm()) { - if (!hasAssumption(*CB->getCaller(), "ompx_no_call_asm") && - !hasAssumption(*CB, "ompx_no_call_asm")) - setHasUnknownCallee(false, Change); - return Change; - } - - // Process callee metadata if available. - if (auto *MD = getCtxI()->getMetadata(LLVMContext::MD_callees)) { - for (auto &Op : MD->operands()) { - Function *Callee = mdconst::extract_or_null(Op); - if (Callee) - addCalledFunction(Callee, Change); - } - return Change; - } - // The most simple case. - ProcessCalledOperand(CB->getCalledOperand()); + ProcessCalledOperand(CB.getCalledOperand()); // Process callback functions. SmallVector CallbackUses; - AbstractCallSite::getCallbackUses(*CB, CallbackUses); + AbstractCallSite::getCallbackUses(CB, CallbackUses); for (const Use *U : CallbackUses) ProcessCalledOperand(U->get()); - - return Change; - } -}; - -struct AACallEdgesFunction : public AACallEdgesImpl { - AACallEdgesFunction(const IRPosition &IRP, Attributor &A) - : AACallEdgesImpl(IRP, A) {} - - /// See AbstractAttribute::updateImpl(...). - ChangeStatus updateImpl(Attributor &A) override { - ChangeStatus Change = ChangeStatus::UNCHANGED; - - auto ProcessCallInst = [&](Instruction &Inst) { - CallBase &CB = static_cast(Inst); - - auto &CBEdges = A.getAAFor( - *this, IRPosition::callsite_function(CB), DepClassTy::REQUIRED); - if (CBEdges.hasNonAsmUnknownCallee()) - setHasUnknownCallee(true, Change); - if (CBEdges.hasUnknownCallee()) - setHasUnknownCallee(false, Change); - - for (Function *F : CBEdges.getOptimisticEdges()) - addCalledFunction(F, Change); - - return true; - }; - - // Visit all callable instructions. - bool UsedAssumedInformation = false; - if (!A.checkForAllCallLikeInstructions(ProcessCallInst, *this, - UsedAssumedInformation)) { - // If we haven't looked at all call like instructions, assume that there - // are unknown callees. - setHasUnknownCallee(true, Change); - } - - return Change; - } -}; - -struct AAFunctionReachabilityFunction : public AAFunctionReachability { -private: - struct QuerySet { - void markReachable(Function *Fn) { - Reachable.insert(Fn); - Unreachable.erase(Fn); - } - - /// If there is no information about the function None is returned. - Optional isCachedReachable(Function &Fn) { - // Assume that we can reach the function. - // TODO: Be more specific with the unknown callee. - if (CanReachUnknownCallee) - return true; - - if (Reachable.count(&Fn)) - return true; - - if (Unreachable.count(&Fn)) - return false; - - return llvm::None; - } - - /// Set of functions that we know for sure is reachable. - DenseSet Reachable; - - /// Set of functions that are unreachable, but might become reachable. - DenseSet Unreachable; - - /// If we can reach a function with a call to a unknown function we assume - /// that we can reach any function. - bool CanReachUnknownCallee = false; - }; - - struct QueryResolver : public QuerySet { - ChangeStatus update(Attributor &A, const AAFunctionReachability &AA, - ArrayRef AAEdgesList) { - ChangeStatus Change = ChangeStatus::UNCHANGED; - - for (auto *AAEdges : AAEdgesList) { - if (AAEdges->hasUnknownCallee()) { - if (!CanReachUnknownCallee) - Change = ChangeStatus::CHANGED; - CanReachUnknownCallee = true; - return Change; - } - } - - for (Function *Fn : make_early_inc_range(Unreachable)) { - if (checkIfReachable(A, AA, AAEdgesList, Fn)) { - Change = ChangeStatus::CHANGED; - markReachable(Fn); - } - } - return Change; - } - - bool isReachable(Attributor &A, const AAFunctionReachability &AA, - ArrayRef AAEdgesList, Function *Fn) { - Optional Cached = isCachedReachable(*Fn); - if (Cached.hasValue()) - return Cached.getValue(); - - // We need to assume that this function can't reach Fn to prevent - // an infinite loop if this function is recursive. - Unreachable.insert(Fn); - - bool Result = checkIfReachable(A, AA, AAEdgesList, Fn); - if (Result) - markReachable(Fn); - return Result; - } - - bool checkIfReachable(Attributor &A, const AAFunctionReachability &AA, - ArrayRef AAEdgesList, - Function *Fn) const { - - // Handle the most trivial case first. - for (auto *AAEdges : AAEdgesList) { - if (!AAEdges->getState().isValidState()) - return true; - - const SetVector &Edges = AAEdges->getOptimisticEdges(); - - if (Edges.count(Fn)) - return true; - } - - SmallVector Deps; - for (auto &AAEdges : AAEdgesList) { - const SetVector &Edges = AAEdges->getOptimisticEdges(); - - for (Function *Edge : Edges) { - // We don't need a dependency if the result is reachable. - const AAFunctionReachability &EdgeReachability = - A.getAAFor( - AA, IRPosition::function(*Edge), DepClassTy::NONE); - Deps.push_back(&EdgeReachability); - - if (EdgeReachability.canReach(A, *Fn)) - return true; - } - } - - // The result is false for now, set dependencies and leave. - for (auto Dep : Deps) - A.recordDependence(AA, *Dep, DepClassTy::REQUIRED); - - return false; - } - }; - - /// Get call edges that can be reached by this instruction. - bool getReachableCallEdges(Attributor &A, const AAReachability &Reachability, - Instruction &Inst, - SmallVector &Result) const { - // Determine call like instructions that we can reach from the inst. - auto CheckCallBase = [&](Instruction &CBInst) { - if (!Reachability.isAssumedReachable(A, Inst, CBInst)) - return true; - - CallBase &CB = static_cast(Inst); - const AACallEdges &AAEdges = A.getAAFor( - *this, IRPosition::callsite_function(CB), DepClassTy::REQUIRED); - - Result.push_back(&AAEdges); - return true; - }; - - bool UsedAssumedInformation = false; - return A.checkForAllCallLikeInstructions(CheckCallBase, *this, - UsedAssumedInformation); - } - - ChangeStatus checkReachableBackwards(Attributor &A, QuerySet &Set) { - ChangeStatus Change = ChangeStatus::UNCHANGED; - - // For all remaining instruction queries, check - // callers. A call inside that function might satisfy the query. - auto CheckCallSite = [&](AbstractCallSite CallSite) { - CallBase *CB = CallSite.getInstruction(); - if (!CB) - return false; - - if (isa(CB)) - return false; - - Instruction *Inst = CB->getNextNonDebugInstruction(); - bool UseBackwards = !Inst->getFunction()->hasFnAttribute("entry.point"); - const AAFunctionReachability &AA = A.getAAFor( - *this, IRPosition::function(*Inst->getFunction()), - DepClassTy::REQUIRED); - for (Function *Fn : make_early_inc_range(Set.Unreachable)) { - if (AA.instructionCanReach(A, *Inst, *Fn, UseBackwards)) { - Set.markReachable(Fn); - Change = ChangeStatus::CHANGED; - } - } - return true; - }; - - bool NoUnknownCall = true; - if (A.checkForAllCallSites(CheckCallSite, *this, true, NoUnknownCall)) - return Change; - - // If we don't know all callsites we have to assume that we can reach fn. - for (auto &QSet : InstQueriesBackwards) { - if (!QSet.second.CanReachUnknownCallee) - Change = ChangeStatus::CHANGED; - QSet.second.CanReachUnknownCallee = true; - } - - return Change; - } - -public: - AAFunctionReachabilityFunction(const IRPosition &IRP, Attributor &A) - : AAFunctionReachability(IRP, A) {} - - bool canReach(Attributor &A, Function &Fn) const override { - const AACallEdges &AAEdges = - A.getAAFor(*this, getIRPosition(), DepClassTy::REQUIRED); - - // Attributor returns attributes as const, so this function has to be - // const for users of this attribute to use it without having to do - // a const_cast. - // This is a hack for us to be able to cache queries. - auto *NonConstThis = const_cast(this); - bool Result = - NonConstThis->WholeFunction.isReachable(A, *this, {&AAEdges}, &Fn); - - return Result; - } - - /// Can \p CB reach \p Fn - bool canReach(Attributor &A, CallBase &CB, Function &Fn) const override { - const AACallEdges &AAEdges = A.getAAFor( - *this, IRPosition::callsite_function(CB), DepClassTy::REQUIRED); - - // Attributor returns attributes as const, so this function has to be - // const for users of this attribute to use it without having to do - // a const_cast. - // This is a hack for us to be able to cache queries. - auto *NonConstThis = const_cast(this); - QueryResolver &CBQuery = NonConstThis->CBQueries[&CB]; - - bool Result = CBQuery.isReachable(A, *this, {&AAEdges}, &Fn); - - return Result; - } - - bool instructionCanReach(Attributor &A, Instruction &Inst, Function &Fn, - bool UseBackwards) const override { - const auto &Reachability = &A.getAAFor( - *this, IRPosition::function(*getAssociatedFunction()), - DepClassTy::REQUIRED); - - SmallVector CallEdges; - bool AllKnown = getReachableCallEdges(A, *Reachability, Inst, CallEdges); - // Attributor returns attributes as const, so this function has to be - // const for users of this attribute to use it without having to do - // a const_cast. - // This is a hack for us to be able to cache queries. - auto *NonConstThis = const_cast(this); - QueryResolver &InstQSet = NonConstThis->InstQueries[&Inst]; - if (!AllKnown) - InstQSet.CanReachUnknownCallee = true; - - bool ForwardsResult = InstQSet.isReachable(A, *this, CallEdges, &Fn); - if (ForwardsResult) - return true; - // We are done. - if (!UseBackwards) - return false; - - QuerySet &InstBackwardsQSet = NonConstThis->InstQueriesBackwards[&Inst]; - - Optional BackwardsCached = InstBackwardsQSet.isCachedReachable(Fn); - if (BackwardsCached.hasValue()) - return BackwardsCached.getValue(); - - // Assume unreachable, to prevent problems. - InstBackwardsQSet.Unreachable.insert(&Fn); - - // Check backwards reachability. - NonConstThis->checkReachableBackwards(A, InstBackwardsQSet); - return InstBackwardsQSet.isCachedReachable(Fn).getValue(); } - - /// See AbstractAttribute::updateImpl(...). - ChangeStatus updateImpl(Attributor &A) override { - const AACallEdges &AAEdges = - A.getAAFor(*this, getIRPosition(), DepClassTy::REQUIRED); - ChangeStatus Change = ChangeStatus::UNCHANGED; - - Change |= WholeFunction.update(A, *this, {&AAEdges}); - - for (auto &CBPair : CBQueries) { - const AACallEdges &AAEdges = A.getAAFor( - *this, IRPosition::callsite_function(*CBPair.first), - DepClassTy::REQUIRED); - - Change |= CBPair.second.update(A, *this, {&AAEdges}); - } - - // Update the Instruction queries. - const AAReachability *Reachability; - if (!InstQueries.empty()) { - Reachability = &A.getAAFor( - *this, IRPosition::function(*getAssociatedFunction()), - DepClassTy::REQUIRED); - } - - // Check for local callbases first. - for (auto &InstPair : InstQueries) { - SmallVector CallEdges; - bool AllKnown = - getReachableCallEdges(A, *Reachability, *InstPair.first, CallEdges); - // Update will return change if we this effects any queries. - if (!AllKnown) - InstPair.second.CanReachUnknownCallee = true; - Change |= InstPair.second.update(A, *this, CallEdges); - } - - // Update backwards queries. - for (auto &QueryPair : InstQueriesBackwards) - Change |= checkReachableBackwards(A, QueryPair.second); - - return Change; - } - - const std::string getAsStr() const override { - size_t QueryCount = - WholeFunction.Reachable.size() + WholeFunction.Unreachable.size(); - - return "FunctionReachability [" + - std::to_string(WholeFunction.Reachable.size()) + "," + - std::to_string(QueryCount) + "]"; - } - - void trackStatistics() const override {} - -private: - bool canReachUnknownCallee() const override { - return WholeFunction.CanReachUnknownCallee; - } - - /// Used to answer if a the whole function can reacha a specific function. - QueryResolver WholeFunction; - - /// Used to answer if a call base inside this function can reach a specific - /// function. - DenseMap CBQueries; - - DenseMap InstQueries; - - // This is for instruction queries than scan backwards. - DenseMap InstQueriesBackwards; }; } // namespace -AACallGraphNode *AACallEdgeIterator::operator*() const { - return static_cast(const_cast( - &A.getOrCreateAAFor(IRPosition::function(**I)))); -} - -void AttributorCallGraph::print() { llvm::WriteGraph(outs(), this); } - const char AAReturnedValues::ID = 0; const char AANoUnwind::ID = 0; const char AANoSync::ID = 0; @@ -9989,7 +9693,6 @@ const char AAValueConstantRange::ID = 0; const char AAPotentialValues::ID = 0; const char AANoUndef::ID = 0; -const char AACallEdges::ID = 0; const char AAFunctionReachability::ID = 0; const char AAPointerInfo::ID = 0; @@ -10093,7 +9796,6 @@ CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoReturn) CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAReturnedValues) CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAMemoryLocation) -CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AACallEdges) CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANonNull) CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoAlias) diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-02-01-ReturnAttrs.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-02-01-ReturnAttrs.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-02-01-ReturnAttrs.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-02-01-ReturnAttrs.ll @@ -92,7 +92,7 @@ ;. ; IS__CGSCC_OPM: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind readonly willreturn } ; IS__CGSCC_OPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn } -; IS__CGSCC_OPM: attributes #[[ATTR2]] = { nounwind readonly willreturn } +; IS__CGSCC_OPM: attributes #[[ATTR2]] = { norecurse nounwind readonly willreturn } ;. ; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } ;. diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-07-02-array-indexing.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-07-02-array-indexing.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-07-02-array-indexing.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-07-02-array-indexing.ll @@ -70,5 +70,5 @@ ; IS__TUNIT____: attributes #[[ATTR1]] = { nofree nosync nounwind readonly willreturn } ;. ; IS__CGSCC____: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind readonly willreturn } -; IS__CGSCC____: attributes #[[ATTR1]] = { nosync nounwind readonly willreturn } +; IS__CGSCC____: attributes #[[ATTR1]] = { norecurse nosync nounwind readonly willreturn } ;. diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/alignment.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/alignment.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/alignment.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/alignment.ll @@ -227,11 +227,11 @@ ; IS__CGSCC_OPM: attributes #[[ATTR1]] = { argmemonly nofree norecurse nosync nounwind willreturn } ; IS__CGSCC_OPM: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind readnone willreturn } ; IS__CGSCC_OPM: attributes #[[ATTR3]] = { nosync nounwind readonly willreturn } -; IS__CGSCC_OPM: attributes #[[ATTR4]] = { nounwind willreturn } +; IS__CGSCC_OPM: attributes #[[ATTR4]] = { norecurse nounwind willreturn } ;. ; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } ; IS__CGSCC_NPM: attributes #[[ATTR1]] = { nosync nounwind readnone willreturn } -; IS__CGSCC_NPM: attributes #[[ATTR2]] = { nounwind readnone willreturn } +; IS__CGSCC_NPM: attributes #[[ATTR2]] = { norecurse nounwind readnone willreturn } ;. ; IS__CGSCC_NPM: [[RNG0]] = !{i32 2, i32 4} ;. diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll @@ -149,7 +149,7 @@ ; IS__TUNIT____: attributes #[[ATTR1:[0-9]+]] = { nofree nosync nounwind willreturn } ;. ; IS__CGSCC_OPM: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind willreturn } -; IS__CGSCC_OPM: attributes #[[ATTR1]] = { nounwind willreturn } +; IS__CGSCC_OPM: attributes #[[ATTR1]] = { norecurse nounwind willreturn } ;. ; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } ;. diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/basictest.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/basictest.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/basictest.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/basictest.ll @@ -141,9 +141,9 @@ ; IS__CGSCC_OPM: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind readonly willreturn } ; IS__CGSCC_OPM: attributes #[[ATTR1]] = { argmemonly nofree norecurse nosync nounwind willreturn } ; IS__CGSCC_OPM: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind readnone willreturn } -; IS__CGSCC_OPM: attributes #[[ATTR3]] = { nosync nounwind readonly willreturn } -; IS__CGSCC_OPM: attributes #[[ATTR4]] = { nounwind willreturn } +; IS__CGSCC_OPM: attributes #[[ATTR3]] = { norecurse nosync nounwind readonly willreturn } +; IS__CGSCC_OPM: attributes #[[ATTR4]] = { norecurse nounwind willreturn } ;. ; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } -; IS__CGSCC_NPM: attributes #[[ATTR1]] = { nosync nounwind readnone willreturn } +; IS__CGSCC_NPM: attributes #[[ATTR1]] = { norecurse nosync nounwind readnone willreturn } ;. diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/byval-2.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/byval-2.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/byval-2.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/byval-2.ll @@ -133,7 +133,7 @@ ; IS__TUNIT____: attributes #[[ATTR1:[0-9]+]] = { nofree nosync nounwind willreturn } ;. ; IS__CGSCC_OPM: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind willreturn } -; IS__CGSCC_OPM: attributes #[[ATTR1]] = { nounwind willreturn } +; IS__CGSCC_OPM: attributes #[[ATTR1]] = { norecurse nounwind willreturn } ;. ; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } ;. diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll @@ -144,15 +144,15 @@ ; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 ; IS__TUNIT_NPM-NEXT: store i32 1, i32* [[TMP1]], align 8 ; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 -; IS__TUNIT_NPM-NEXT: [[S_CAST1:%.*]] = bitcast %struct.ss* [[S]] to i32* -; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[S_CAST1]], align 8 -; IS__TUNIT_NPM-NEXT: [[S_0_12:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 -; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i64, i64* [[S_0_12]], align 8 -; IS__TUNIT_NPM-NEXT: [[C0:%.*]] = call i32 @f(i32 [[TMP0]], i64 [[TMP1]]) #[[ATTR2:[0-9]+]] ; IS__TUNIT_NPM-NEXT: [[S_CAST:%.*]] = bitcast %struct.ss* [[S]] to i32* -; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[S_CAST]], align 32 +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[S_CAST]], align 8 ; IS__TUNIT_NPM-NEXT: [[S_0_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 -; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = load i64, i64* [[S_0_1]], align 32 +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i64, i64* [[S_0_1]], align 8 +; IS__TUNIT_NPM-NEXT: [[C0:%.*]] = call i32 @f(i32 [[TMP0]], i64 [[TMP1]]) #[[ATTR2:[0-9]+]] +; IS__TUNIT_NPM-NEXT: [[S_CAST1:%.*]] = bitcast %struct.ss* [[S]] to i32* +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[S_CAST1]], align 32 +; IS__TUNIT_NPM-NEXT: [[S_0_12:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 +; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = load i64, i64* [[S_0_12]], align 32 ; IS__TUNIT_NPM-NEXT: [[C1:%.*]] = call i32 @g(i32 [[TMP2]], i64 [[TMP3]]) #[[ATTR2]] ; IS__TUNIT_NPM-NEXT: [[A:%.*]] = add i32 [[C0]], [[C1]] ; IS__TUNIT_NPM-NEXT: ret i32 [[A]] @@ -199,7 +199,7 @@ ;. ; IS__CGSCC_OPM: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind willreturn } ; IS__CGSCC_OPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn } -; IS__CGSCC_OPM: attributes #[[ATTR2]] = { nounwind willreturn } +; IS__CGSCC_OPM: attributes #[[ATTR2]] = { norecurse nounwind willreturn } ;. ; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } ;. diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow.ll @@ -64,5 +64,5 @@ ; IS__TUNIT____: attributes #[[ATTR1]] = { nofree nosync nounwind readonly willreturn } ;. ; IS__CGSCC____: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind readonly willreturn } -; IS__CGSCC____: attributes #[[ATTR1]] = { nosync nounwind readonly willreturn } +; IS__CGSCC____: attributes #[[ATTR1]] = { norecurse nosync nounwind readonly willreturn } ;. diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow2.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow2.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow2.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow2.ll @@ -105,7 +105,7 @@ ;. ; IS__CGSCC_OPM: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind readonly willreturn } ; IS__CGSCC_OPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn } -; IS__CGSCC_OPM: attributes #[[ATTR2]] = { nounwind readonly willreturn } +; IS__CGSCC_OPM: attributes #[[ATTR2]] = { norecurse nounwind readonly willreturn } ;. ; IS__CGSCC_NPM: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind readonly willreturn } ; IS__CGSCC_NPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn } diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/crash.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/crash.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/crash.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/crash.ll @@ -24,7 +24,7 @@ ; IS__CGSCC____-LABEL: define {{[^@]+}}@zot ; IS__CGSCC____-SAME: () #[[ATTR0:[0-9]+]] personality i32 (...)* @wibble { ; IS__CGSCC____-NEXT: bb: -; IS__CGSCC____-NEXT: call void @hoge() #[[ATTR2:[0-9]+]] +; IS__CGSCC____-NEXT: call void @hoge() #[[ATTR3:[0-9]+]] ; IS__CGSCC____-NEXT: unreachable ; IS__CGSCC____: bb1: ; IS__CGSCC____-NEXT: unreachable @@ -75,8 +75,9 @@ } define internal i1 @eggs(i8* %arg) { +; IS__CGSCC____: Function Attrs: norecurse ; IS__CGSCC____-LABEL: define {{[^@]+}}@eggs -; IS__CGSCC____-SAME: (i8* [[ARG:%.*]]) { +; IS__CGSCC____-SAME: (i8* [[ARG:%.*]]) #[[ATTR1:[0-9]+]] { ; IS__CGSCC____-NEXT: bb: ; IS__CGSCC____-NEXT: [[TMP:%.*]] = call zeroext i1 @barney() ; IS__CGSCC____-NEXT: unreachable @@ -89,7 +90,7 @@ define internal i1 @barney(i8* %arg) { ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@barney -; IS__CGSCC____-SAME: () #[[ATTR1:[0-9]+]] { +; IS__CGSCC____-SAME: () #[[ATTR2:[0-9]+]] { ; IS__CGSCC____-NEXT: bb: ; IS__CGSCC____-NEXT: ret i1 undef ; @@ -143,6 +144,7 @@ ; IS__TUNIT____: attributes #[[ATTR1]] = { noreturn nounwind readnone } ;. ; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse noreturn nosync nounwind readnone willreturn } -; IS__CGSCC____: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn } -; IS__CGSCC____: attributes #[[ATTR2]] = { noreturn nounwind readnone } +; IS__CGSCC____: attributes #[[ATTR1]] = { norecurse } +; IS__CGSCC____: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind readnone willreturn } +; IS__CGSCC____: attributes #[[ATTR3]] = { noreturn nounwind readnone } ;. diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/inalloca.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/inalloca.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/inalloca.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/inalloca.ll @@ -114,5 +114,5 @@ ;. ; IS__CGSCC____: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind readonly willreturn } ; IS__CGSCC____: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn } -; IS__CGSCC____: attributes #[[ATTR2]] = { nounwind readonly willreturn } +; IS__CGSCC____: attributes #[[ATTR2]] = { norecurse nounwind readonly willreturn } ;. diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/live_called_from_dead.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/live_called_from_dead.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/live_called_from_dead.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/live_called_from_dead.ll @@ -10,7 +10,9 @@ ; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = call i32 @test(i32* null) ; IS__CGSCC_OPM-NEXT: ret void ; -; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@dead() { +; IS__CGSCC_NPM: Function Attrs: norecurse +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@dead +; IS__CGSCC_NPM-SAME: () #[[ATTR0:[0-9]+]] { ; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = call i32 @test(i32* nonnull align 1073741824 dereferenceable(4) null) ; IS__CGSCC_NPM-NEXT: ret void ; @@ -31,7 +33,7 @@ ; ; IS__CGSCC_NPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test -; IS__CGSCC_NPM-SAME: (i32* noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[X:%.*]]) #[[ATTR0:[0-9]+]] { +; IS__CGSCC_NPM-SAME: (i32* noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[X:%.*]]) #[[ATTR1:[0-9]+]] { ; IS__CGSCC_NPM-NEXT: br i1 true, label [[LIVE:%.*]], label [[DEAD:%.*]] ; IS__CGSCC_NPM: live: ; IS__CGSCC_NPM-NEXT: store i32 0, i32* [[X]], align 4 @@ -59,9 +61,9 @@ ; ; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@caller -; IS__CGSCC_NPM-SAME: () #[[ATTR1:[0-9]+]] { +; IS__CGSCC_NPM-SAME: () #[[ATTR2:[0-9]+]] { ; IS__CGSCC_NPM-NEXT: [[A:%.*]] = alloca i32, align 4 -; IS__CGSCC_NPM-NEXT: [[C:%.*]] = call i32 @test(i32* noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A]]) #[[ATTR2:[0-9]+]] +; IS__CGSCC_NPM-NEXT: [[C:%.*]] = call i32 @test(i32* noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A]]) #[[ATTR3:[0-9]+]] ; IS__CGSCC_NPM-NEXT: ret i32 undef ; %A = alloca i32 @@ -77,17 +79,11 @@ ; IS__TUNIT____-NEXT: [[B:%.*]] = alloca i32, align 4 ; IS__TUNIT____-NEXT: ret i32 0 ; -; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn -; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@callercaller -; IS__CGSCC_OPM-SAME: () #[[ATTR2:[0-9]+]] { -; IS__CGSCC_OPM-NEXT: [[B:%.*]] = alloca i32, align 4 -; IS__CGSCC_OPM-NEXT: ret i32 0 -; -; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn -; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@callercaller -; IS__CGSCC_NPM-SAME: () #[[ATTR1]] { -; IS__CGSCC_NPM-NEXT: [[B:%.*]] = alloca i32, align 4 -; IS__CGSCC_NPM-NEXT: ret i32 0 +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@callercaller +; IS__CGSCC____-SAME: () #[[ATTR2:[0-9]+]] { +; IS__CGSCC____-NEXT: [[B:%.*]] = alloca i32, align 4 +; IS__CGSCC____-NEXT: ret i32 0 ; %B = alloca i32 store i32 2, i32* %B @@ -103,7 +99,8 @@ ; IS__CGSCC_OPM: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind readnone willreturn } ; IS__CGSCC_OPM: attributes #[[ATTR3]] = { nofree nosync nounwind willreturn writeonly } ;. -; IS__CGSCC_NPM: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly } -; IS__CGSCC_NPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn } -; IS__CGSCC_NPM: attributes #[[ATTR2]] = { nofree nosync nounwind willreturn writeonly } +; IS__CGSCC_NPM: attributes #[[ATTR0]] = { norecurse } +; IS__CGSCC_NPM: attributes #[[ATTR1]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly } +; IS__CGSCC_NPM: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind readnone willreturn } +; IS__CGSCC_NPM: attributes #[[ATTR3]] = { nofree norecurse nosync nounwind willreturn writeonly } ;. diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/live_called_from_dead_2.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/live_called_from_dead_2.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/live_called_from_dead_2.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/live_called_from_dead_2.ll @@ -10,7 +10,9 @@ ; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = call i32 @test(i32* align 1073741824 null) ; IS__CGSCC_OPM-NEXT: ret void ; -; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@dead() { +; IS__CGSCC_NPM: Function Attrs: norecurse +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@dead +; IS__CGSCC_NPM-SAME: () #[[ATTR0:[0-9]+]] { ; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = call i32 @test(i32* nonnull align 1073741824 dereferenceable(4) null) ; IS__CGSCC_NPM-NEXT: ret void ; @@ -31,7 +33,7 @@ ; ; IS__CGSCC_NPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test -; IS__CGSCC_NPM-SAME: (i32* noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[X:%.*]]) #[[ATTR0:[0-9]+]] { +; IS__CGSCC_NPM-SAME: (i32* noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[X:%.*]]) #[[ATTR1:[0-9]+]] { ; IS__CGSCC_NPM-NEXT: br i1 true, label [[LIVE:%.*]], label [[DEAD:%.*]] ; IS__CGSCC_NPM: live: ; IS__CGSCC_NPM-NEXT: store i32 0, i32* [[X]], align 4 @@ -59,9 +61,9 @@ ; ; IS__CGSCC_NPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@caller -; IS__CGSCC_NPM-SAME: (i32* noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[B:%.*]]) #[[ATTR0]] { +; IS__CGSCC_NPM-SAME: (i32* noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[B:%.*]]) #[[ATTR1]] { ; IS__CGSCC_NPM-NEXT: [[A:%.*]] = alloca i32, align 4 -; IS__CGSCC_NPM-NEXT: [[C:%.*]] = call i32 @test(i32* noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[B]]) #[[ATTR2:[0-9]+]] +; IS__CGSCC_NPM-NEXT: [[C:%.*]] = call i32 @test(i32* noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[B]]) #[[ATTR3:[0-9]+]] ; IS__CGSCC_NPM-NEXT: ret i32 undef ; %A = alloca i32 @@ -87,9 +89,9 @@ ; ; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@callercaller -; IS__CGSCC_NPM-SAME: () #[[ATTR1:[0-9]+]] { +; IS__CGSCC_NPM-SAME: () #[[ATTR2:[0-9]+]] { ; IS__CGSCC_NPM-NEXT: [[B:%.*]] = alloca i32, align 4 -; IS__CGSCC_NPM-NEXT: [[X:%.*]] = call i32 @caller(i32* noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[B]]) #[[ATTR3:[0-9]+]] +; IS__CGSCC_NPM-NEXT: [[X:%.*]] = call i32 @caller(i32* noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[B]]) #[[ATTR4:[0-9]+]] ; IS__CGSCC_NPM-NEXT: ret i32 0 ; %B = alloca i32 @@ -108,8 +110,9 @@ ; IS__CGSCC_OPM: attributes #[[ATTR2]] = { nofree nosync nounwind willreturn writeonly } ; IS__CGSCC_OPM: attributes #[[ATTR3]] = { nounwind willreturn writeonly } ;. -; IS__CGSCC_NPM: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly } -; IS__CGSCC_NPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn } -; IS__CGSCC_NPM: attributes #[[ATTR2]] = { nofree nosync nounwind willreturn writeonly } -; IS__CGSCC_NPM: attributes #[[ATTR3]] = { nounwind willreturn writeonly } +; IS__CGSCC_NPM: attributes #[[ATTR0]] = { norecurse } +; IS__CGSCC_NPM: attributes #[[ATTR1]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly } +; IS__CGSCC_NPM: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind readnone willreturn } +; IS__CGSCC_NPM: attributes #[[ATTR3]] = { nofree norecurse nosync nounwind willreturn writeonly } +; IS__CGSCC_NPM: attributes #[[ATTR4]] = { norecurse nounwind willreturn writeonly } ;. diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/musttail.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/musttail.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/musttail.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/musttail.ll @@ -186,7 +186,7 @@ ; IS__CGSCC____: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn } ; IS__CGSCC____: attributes #[[ATTR2]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly } ; IS__CGSCC____: attributes #[[ATTR3]] = { argmemonly nofree norecurse nosync nounwind willreturn } -; IS__CGSCC____: attributes #[[ATTR4]] = { nosync nounwind readonly willreturn } +; IS__CGSCC____: attributes #[[ATTR4]] = { norecurse nosync nounwind readonly willreturn } ; IS__CGSCC____: attributes #[[ATTR5]] = { nounwind willreturn writeonly } -; IS__CGSCC____: attributes #[[ATTR6]] = { nosync nounwind willreturn } +; IS__CGSCC____: attributes #[[ATTR6]] = { norecurse nosync nounwind willreturn } ;. diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/pr32917.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/pr32917.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/pr32917.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/pr32917.ll @@ -64,5 +64,5 @@ ; IS__TUNIT____: attributes #[[ATTR0]] = { nofree nosync nounwind willreturn } ;. ; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind willreturn } -; IS__CGSCC____: attributes #[[ATTR1]] = { nounwind willreturn } +; IS__CGSCC____: attributes #[[ATTR1]] = { norecurse nounwind willreturn } ;. diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/reserve-tbaa.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/reserve-tbaa.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/reserve-tbaa.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/reserve-tbaa.ll @@ -98,7 +98,7 @@ ; IS__TUNIT____: attributes #[[ATTR0]] = { nofree nosync nounwind willreturn } ;. ; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind willreturn } -; IS__CGSCC____: attributes #[[ATTR1]] = { nounwind willreturn } +; IS__CGSCC____: attributes #[[ATTR1]] = { norecurse nounwind willreturn } ;. ; CHECK: [[META0:![0-9]+]] = !{!1, !1, i64 0} ; CHECK: [[META1:![0-9]+]] = !{!"int", !2, i64 0} diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/sret.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/sret.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/sret.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/sret.ll @@ -108,5 +108,5 @@ ;. ; IS__CGSCC____: attributes #[[ATTR0:[0-9]+]] = { argmemonly nofree norecurse nosync nounwind willreturn } ; IS__CGSCC____: attributes #[[ATTR1:[0-9]+]] = { nofree norecurse nosync nounwind readnone willreturn } -; IS__CGSCC____: attributes #[[ATTR2:[0-9]+]] = { nounwind willreturn } +; IS__CGSCC____: attributes #[[ATTR2:[0-9]+]] = { norecurse nounwind willreturn } ;. diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/2009-09-24-byval-ptr.ll b/llvm/test/Transforms/Attributor/IPConstantProp/2009-09-24-byval-ptr.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/2009-09-24-byval-ptr.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/2009-09-24-byval-ptr.ll @@ -289,15 +289,15 @@ ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@unions_v2 ; IS__TUNIT_NPM-SAME: () #[[ATTR0]] { ; IS__TUNIT_NPM-NEXT: entry: -; IS__TUNIT_NPM-NEXT: [[MYSTR_CAST1:%.*]] = bitcast %struct.MYstr* @mystr to i8* -; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i8, i8* [[MYSTR_CAST1]], align 8 -; IS__TUNIT_NPM-NEXT: [[MYSTR_0_12:%.*]] = getelementptr [[STRUCT_MYSTR:%.*]], %struct.MYstr* @mystr, i32 0, i32 1 -; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[MYSTR_0_12]], align 8 -; IS__TUNIT_NPM-NEXT: call void @vfu1(i8 [[TMP0]], i32 [[TMP1]]) #[[ATTR0]] ; IS__TUNIT_NPM-NEXT: [[MYSTR_CAST:%.*]] = bitcast %struct.MYstr* @mystr to i8* -; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = load i8, i8* [[MYSTR_CAST]], align 8 -; IS__TUNIT_NPM-NEXT: [[MYSTR_0_1:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* @mystr, i32 0, i32 1 -; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[MYSTR_0_1]], align 8 +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i8, i8* [[MYSTR_CAST]], align 8 +; IS__TUNIT_NPM-NEXT: [[MYSTR_0_1:%.*]] = getelementptr [[STRUCT_MYSTR:%.*]], %struct.MYstr* @mystr, i32 0, i32 1 +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[MYSTR_0_1]], align 8 +; IS__TUNIT_NPM-NEXT: call void @vfu1(i8 [[TMP0]], i32 [[TMP1]]) #[[ATTR0]] +; IS__TUNIT_NPM-NEXT: [[MYSTR_CAST1:%.*]] = bitcast %struct.MYstr* @mystr to i8* +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = load i8, i8* [[MYSTR_CAST1]], align 8 +; IS__TUNIT_NPM-NEXT: [[MYSTR_0_12:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* @mystr, i32 0, i32 1 +; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[MYSTR_0_12]], align 8 ; IS__TUNIT_NPM-NEXT: [[RESULT:%.*]] = call i32 @vfu2_v2(i8 [[TMP2]], i32 [[TMP3]]) #[[ATTR0]] ; IS__TUNIT_NPM-NEXT: ret i32 [[RESULT]] ; @@ -306,7 +306,7 @@ ; IS__CGSCC_OPM-SAME: () #[[ATTR0]] { ; IS__CGSCC_OPM-NEXT: entry: ; IS__CGSCC_OPM-NEXT: call void @vfu1(%struct.MYstr* noalias nocapture nofree noundef nonnull readonly byval([[STRUCT_MYSTR:%.*]]) align 8 dereferenceable(8) @mystr) #[[ATTR0]] -; IS__CGSCC_OPM-NEXT: [[RESULT:%.*]] = call i32 @vfu2_v2(%struct.MYstr* noalias nocapture nofree noundef nonnull readonly byval([[STRUCT_MYSTR]]) align 8 dereferenceable(8) @mystr) #[[ATTR0]] +; IS__CGSCC_OPM-NEXT: [[RESULT:%.*]] = call i32 @vfu2_v2(%struct.MYstr* noalias nocapture nofree noundef nonnull readonly byval([[STRUCT_MYSTR]]) align 8 dereferenceable(8) @mystr) #[[ATTR2:[0-9]+]] ; IS__CGSCC_OPM-NEXT: ret i32 [[RESULT]] ; ; IS__CGSCC_NPM: Function Attrs: nounwind @@ -324,3 +324,11 @@ ;. ; IS__TUNIT____: attributes #[[ATTR0:[0-9]+]] = { nounwind } ; IS__TUNIT____: attributes #[[ATTR1:[0-9]+]] = { argmemonly nofree nosync nounwind readonly willreturn } +;. +; IS__CGSCC_OPM: attributes #[[ATTR0]] = { nounwind } +; IS__CGSCC_OPM: attributes #[[ATTR1]] = { argmemonly nofree norecurse nosync nounwind readonly willreturn } +; IS__CGSCC_OPM: attributes #[[ATTR2]] = { nounwind readonly } +;. +; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nounwind } +; IS__CGSCC_NPM: attributes #[[ATTR1]] = { argmemonly nofree norecurse nosync nounwind readonly willreturn } +;. diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/return-argument.ll b/llvm/test/Transforms/Attributor/IPConstantProp/return-argument.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/return-argument.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/return-argument.ll @@ -133,7 +133,7 @@ ; IS__CGSCC_OPM-NEXT: [[W:%.*]] = call align 4 i32* @incdec(i1 [[C]], i32* noalias nofree noundef nonnull align 4 dereferenceable(4) "no-capture-maybe-returned" [[Q]]) #[[ATTR2:[0-9]+]] ; IS__CGSCC_OPM-NEXT: [[S1:%.*]] = call { i32, i32 } @foo(i32 noundef 1, i32 noundef 2) #[[ATTR3:[0-9]+]] ; IS__CGSCC_OPM-NEXT: [[X1:%.*]] = extractvalue { i32, i32 } [[S1]], 0 -; IS__CGSCC_OPM-NEXT: [[S2:%.*]] = call { i32, i32 } @foo(i32 noundef 3, i32 noundef 4) #[[ATTR4:[0-9]+]] +; IS__CGSCC_OPM-NEXT: [[S2:%.*]] = call { i32, i32 } @foo(i32 noundef 3, i32 noundef 4) #[[ATTR3]] ; IS__CGSCC_OPM-NEXT: br label [[OK:%.*]] ; IS__CGSCC_OPM: OK: ; IS__CGSCC_OPM-NEXT: [[X2:%.*]] = extractvalue { i32, i32 } [[S2]], 0 @@ -152,7 +152,7 @@ ; IS__CGSCC_NPM-NEXT: [[W:%.*]] = call i32* @incdec(i1 [[C]], i32* noalias nofree noundef nonnull align 4 dereferenceable(4) "no-capture-maybe-returned" [[Q]]) #[[ATTR2:[0-9]+]] ; IS__CGSCC_NPM-NEXT: [[S1:%.*]] = call { i32, i32 } @foo(i32 noundef 1, i32 noundef 2) #[[ATTR3:[0-9]+]] ; IS__CGSCC_NPM-NEXT: [[X1:%.*]] = extractvalue { i32, i32 } [[S1]], 0 -; IS__CGSCC_NPM-NEXT: [[S2:%.*]] = call { i32, i32 } @foo(i32 noundef 3, i32 noundef 4) #[[ATTR4:[0-9]+]] +; IS__CGSCC_NPM-NEXT: [[S2:%.*]] = call { i32, i32 } @foo(i32 noundef 3, i32 noundef 4) #[[ATTR3]] ; IS__CGSCC_NPM-NEXT: br label [[OK:%.*]] ; IS__CGSCC_NPM: OK: ; IS__CGSCC_NPM-NEXT: [[X2:%.*]] = extractvalue { i32, i32 } [[S2]], 0 @@ -199,6 +199,5 @@ ; IS__CGSCC____: attributes #[[ATTR0:[0-9]+]] = { argmemonly nofree norecurse nosync nounwind willreturn } ; IS__CGSCC____: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn } ; IS__CGSCC____: attributes #[[ATTR2:[0-9]+]] = { nounwind willreturn } -; IS__CGSCC____: attributes #[[ATTR3:[0-9]+]] = { readnone willreturn } -; IS__CGSCC____: attributes #[[ATTR4:[0-9]+]] = { nounwind readnone willreturn } +; IS__CGSCC____: attributes #[[ATTR3:[0-9]+]] = { norecurse nounwind readnone willreturn } ;. diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/return-constants.ll b/llvm/test/Transforms/Attributor/IPConstantProp/return-constants.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/return-constants.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/return-constants.ll @@ -128,10 +128,10 @@ ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@caller2 ; IS__CGSCC____-SAME: (i1 [[Q:%.*]]) #[[ATTR0]] { -; IS__CGSCC____-NEXT: [[X:%.*]] = call [[TMP0:%.*]] @foo(i1 [[Q]]) #[[ATTR1]] +; IS__CGSCC____-NEXT: [[X:%.*]] = call [[TMP0:%.*]] @foo(i1 [[Q]]) #[[ATTR2:[0-9]+]] ; IS__CGSCC____-NEXT: [[A:%.*]] = extractvalue [[TMP0]] [[X]], 0 ; IS__CGSCC____-NEXT: [[B:%.*]] = extractvalue [[TMP0]] [[X]], 1 -; IS__CGSCC____-NEXT: [[Y:%.*]] = call [[TMP0]] @bar(i1 [[Q]]) #[[ATTR1]] +; IS__CGSCC____-NEXT: [[Y:%.*]] = call [[TMP0]] @bar(i1 [[Q]]) #[[ATTR2]] ; IS__CGSCC____-NEXT: [[C:%.*]] = extractvalue [[TMP0]] [[Y]], 0 ; IS__CGSCC____-NEXT: [[D:%.*]] = extractvalue [[TMP0]] [[Y]], 1 ; IS__CGSCC____-NEXT: [[M:%.*]] = add i32 [[A]], [[C]] @@ -156,4 +156,5 @@ ;. ; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } ; IS__CGSCC____: attributes #[[ATTR1]] = { readnone willreturn } +; IS__CGSCC____: attributes #[[ATTR2]] = { norecurse nounwind readnone willreturn } ;. diff --git a/llvm/test/Transforms/Attributor/align.ll b/llvm/test/Transforms/Attributor/align.ll --- a/llvm/test/Transforms/Attributor/align.ll +++ b/llvm/test/Transforms/Attributor/align.ll @@ -205,7 +205,7 @@ ; IS__CGSCC_OPM-NEXT: [[TMP8:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP6]], [[TMP5]] ] ; IS__CGSCC_OPM-NEXT: ret i8* [[TMP8]] ; -; IS__CGSCC_NPM: Function Attrs: noinline nounwind uwtable +; IS__CGSCC_NPM: Function Attrs: noinline norecurse nounwind uwtable ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f2 ; IS__CGSCC_NPM-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { ; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null @@ -342,7 +342,7 @@ ; IS__CGSCC_OPM-NEXT: [[TMP8:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP6]], [[TMP5]] ] ; IS__CGSCC_OPM-NEXT: ret i8* [[TMP8]] ; -; IS__CGSCC_NPM: Function Attrs: noinline nounwind uwtable +; IS__CGSCC_NPM: Function Attrs: noinline norecurse nounwind uwtable ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f2b ; IS__CGSCC_NPM-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR2]] { ; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null @@ -1398,7 +1398,7 @@ ;. ; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree noinline norecurse nosync nounwind readnone uwtable willreturn } ; IS__CGSCC_NPM: attributes #[[ATTR1]] = { nofree noinline norecurse noreturn nosync nounwind readnone uwtable willreturn } -; IS__CGSCC_NPM: attributes #[[ATTR2]] = { noinline nounwind uwtable } +; IS__CGSCC_NPM: attributes #[[ATTR2]] = { noinline norecurse nounwind uwtable } ; IS__CGSCC_NPM: attributes #[[ATTR3]] = { nounwind } ; IS__CGSCC_NPM: attributes #[[ATTR4]] = { nofree nosync nounwind } ; IS__CGSCC_NPM: attributes #[[ATTR5]] = { argmemonly nofree norecurse nosync nounwind readonly willreturn } diff --git a/llvm/test/Transforms/Attributor/dereferenceable-1.ll b/llvm/test/Transforms/Attributor/dereferenceable-1.ll --- a/llvm/test/Transforms/Attributor/dereferenceable-1.ll +++ b/llvm/test/Transforms/Attributor/dereferenceable-1.ll @@ -1177,7 +1177,7 @@ ; IS__CGSCC_OPM: attributes #[[ATTR4]] = { argmemonly nofree norecurse nosync nounwind } ; IS__CGSCC_OPM: attributes #[[ATTR5]] = { argmemonly nofree nosync nounwind writeonly } ; IS__CGSCC_OPM: attributes #[[ATTR6:[0-9]+]] = { inaccessiblememonly nofree nosync nounwind willreturn } -; IS__CGSCC_OPM: attributes #[[ATTR7]] = { nosync nounwind writeonly } +; IS__CGSCC_OPM: attributes #[[ATTR7]] = { norecurse nosync nounwind writeonly } ; IS__CGSCC_OPM: attributes #[[ATTR8]] = { nofree nosync nounwind writeonly } ; IS__CGSCC_OPM: attributes #[[ATTR9]] = { willreturn } ; IS__CGSCC_OPM: attributes #[[ATTR10]] = { nounwind } @@ -1188,7 +1188,7 @@ ; IS__CGSCC_NPM: attributes #[[ATTR3]] = { argmemonly nofree norecurse nosync nounwind willreturn } ; IS__CGSCC_NPM: attributes #[[ATTR4]] = { argmemonly nofree nosync nounwind writeonly } ; IS__CGSCC_NPM: attributes #[[ATTR5:[0-9]+]] = { inaccessiblememonly nofree nosync nounwind willreturn } -; IS__CGSCC_NPM: attributes #[[ATTR6]] = { nosync nounwind willreturn writeonly } +; IS__CGSCC_NPM: attributes #[[ATTR6]] = { norecurse nosync nounwind willreturn writeonly } ; IS__CGSCC_NPM: attributes #[[ATTR7]] = { nofree nosync nounwind writeonly } ; IS__CGSCC_NPM: attributes #[[ATTR8]] = { willreturn } ; IS__CGSCC_NPM: attributes #[[ATTR9]] = { nounwind } diff --git a/llvm/test/Transforms/Attributor/internal-noalias.ll b/llvm/test/Transforms/Attributor/internal-noalias.ll --- a/llvm/test/Transforms/Attributor/internal-noalias.ll +++ b/llvm/test/Transforms/Attributor/internal-noalias.ll @@ -108,7 +108,7 @@ ; IS__CGSCC____-NEXT: [[B:%.*]] = alloca i32, align 4 ; IS__CGSCC____-NEXT: store i32 5, i32* [[B]], align 4 ; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call i32 @noalias_args(i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B]]) #[[ATTR4]] -; IS__CGSCC____-NEXT: [[CALL2:%.*]] = call i32 @noalias_args_argmem(i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B]]) #[[ATTR4]] +; IS__CGSCC____-NEXT: [[CALL2:%.*]] = call i32 @noalias_args_argmem(i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B]]) #[[ATTR5:[0-9]+]] ; IS__CGSCC____-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL1]], [[CALL2]] ; IS__CGSCC____-NEXT: ret i32 [[ADD]] ; @@ -192,7 +192,7 @@ ; IS__CGSCC_OPM-SAME: () #[[ATTR2:[0-9]+]] { ; IS__CGSCC_OPM-NEXT: [[B:%.*]] = alloca i32, align 4 ; IS__CGSCC_OPM-NEXT: store i32 5, i32* [[B]], align 4 -; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call i32 @noalias_args_argmem_ro(i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B]]) #[[ATTR5:[0-9]+]] +; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call i32 @noalias_args_argmem_ro(i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B]]) #[[ATTR6:[0-9]+]] ; IS__CGSCC_OPM-NEXT: ret i32 [[CALL]] ; ; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn @@ -240,7 +240,7 @@ ; IS__CGSCC_OPM-SAME: () #[[ATTR2]] { ; IS__CGSCC_OPM-NEXT: [[B:%.*]] = alloca i32, align 4 ; IS__CGSCC_OPM-NEXT: store i32 5, i32* [[B]], align 4 -; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call i32 @noalias_args_argmem_rn(i32* noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[B]]) #[[ATTR6:[0-9]+]] +; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call i32 @noalias_args_argmem_rn(i32* noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[B]]) #[[ATTR7:[0-9]+]] ; IS__CGSCC_OPM-NEXT: ret i32 [[CALL]] ; ; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn @@ -248,7 +248,7 @@ ; IS__CGSCC_NPM-SAME: () #[[ATTR2]] { ; IS__CGSCC_NPM-NEXT: [[B:%.*]] = alloca i32, align 4 ; IS__CGSCC_NPM-NEXT: store i32 5, i32* [[B]], align 4 -; IS__CGSCC_NPM-NEXT: [[CALL:%.*]] = call i32 @noalias_args_argmem_rn(i32* noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[B]]) #[[ATTR5:[0-9]+]] +; IS__CGSCC_NPM-NEXT: [[CALL:%.*]] = call i32 @noalias_args_argmem_rn(i32* noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[B]]) #[[ATTR6:[0-9]+]] ; IS__CGSCC_NPM-NEXT: ret i32 [[CALL]] ; %B = alloca i32, align 4 @@ -271,14 +271,16 @@ ; IS__CGSCC_OPM: attributes #[[ATTR1]] = { argmemonly nofree noinline norecurse nosync nounwind uwtable willreturn } ; IS__CGSCC_OPM: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind readnone willreturn } ; IS__CGSCC_OPM: attributes #[[ATTR3]] = { nounwind readonly } -; IS__CGSCC_OPM: attributes #[[ATTR4]] = { nosync nounwind readonly } -; IS__CGSCC_OPM: attributes #[[ATTR5]] = { nounwind readonly willreturn } -; IS__CGSCC_OPM: attributes #[[ATTR6]] = { nounwind willreturn } +; IS__CGSCC_OPM: attributes #[[ATTR4]] = { norecurse nosync nounwind readonly } +; IS__CGSCC_OPM: attributes #[[ATTR5]] = { nosync nounwind readonly } +; IS__CGSCC_OPM: attributes #[[ATTR6]] = { norecurse nounwind readonly willreturn } +; IS__CGSCC_OPM: attributes #[[ATTR7]] = { norecurse nounwind willreturn } ;. ; IS__CGSCC_NPM: attributes #[[ATTR0]] = { argmemonly nofree noinline norecurse nosync nounwind readonly uwtable willreturn } ; IS__CGSCC_NPM: attributes #[[ATTR1]] = { argmemonly nofree noinline norecurse nosync nounwind uwtable willreturn } ; IS__CGSCC_NPM: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind readnone willreturn } ; IS__CGSCC_NPM: attributes #[[ATTR3]] = { nounwind readonly } -; IS__CGSCC_NPM: attributes #[[ATTR4]] = { nosync nounwind readonly } -; IS__CGSCC_NPM: attributes #[[ATTR5]] = { nounwind willreturn } +; IS__CGSCC_NPM: attributes #[[ATTR4]] = { norecurse nosync nounwind readonly } +; IS__CGSCC_NPM: attributes #[[ATTR5]] = { nosync nounwind readonly } +; IS__CGSCC_NPM: attributes #[[ATTR6]] = { norecurse nounwind willreturn } ;. diff --git a/llvm/test/Transforms/Attributor/liveness.ll b/llvm/test/Transforms/Attributor/liveness.ll --- a/llvm/test/Transforms/Attributor/liveness.ll +++ b/llvm/test/Transforms/Attributor/liveness.ll @@ -824,7 +824,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree noreturn nosync nounwind ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test_unreachable ; NOT_CGSCC_NPM-SAME: () #[[ATTR0]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14:[0-9]+]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15:[0-9]+]] ; NOT_CGSCC_NPM-NEXT: call void @test_unreachable() #[[ATTR0]] ; NOT_CGSCC_NPM-NEXT: unreachable ; @@ -1053,7 +1053,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_a0 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1069,7 +1069,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_a1 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1085,7 +1085,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_a2 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1101,7 +1101,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_a3 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1117,7 +1117,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_a4 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1133,7 +1133,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_a5 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1149,7 +1149,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_a6 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1165,7 +1165,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_a7 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1181,7 +1181,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_a8 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1197,7 +1197,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_a9 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1213,7 +1213,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_a10 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1229,7 +1229,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_a11 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1245,7 +1245,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_a12 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1261,7 +1261,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_a13 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1277,7 +1277,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_a14 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1293,7 +1293,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_a15 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1309,7 +1309,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_b0 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1325,7 +1325,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_b1 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1341,7 +1341,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_b2 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1357,7 +1357,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_b3 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1373,7 +1373,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_b4 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1389,7 +1389,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_b5 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1405,7 +1405,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_b6 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1421,7 +1421,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_b7 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1437,7 +1437,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_b8 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1453,7 +1453,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_b9 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1469,7 +1469,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_b10 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1485,7 +1485,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_b11 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1501,7 +1501,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_b12 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1517,7 +1517,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_b13 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1533,7 +1533,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_b14 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1549,7 +1549,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_b15 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1565,7 +1565,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_c0 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1581,7 +1581,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_c1 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1597,7 +1597,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_c2 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1613,7 +1613,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_c3 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1629,7 +1629,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_c4 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1645,7 +1645,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_c5 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1661,7 +1661,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_c6 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1677,7 +1677,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_c7 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1693,7 +1693,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_c8 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1709,7 +1709,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_c9 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1725,7 +1725,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_c10 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1741,7 +1741,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_c11 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1757,7 +1757,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_c12 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1773,7 +1773,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_c13 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1789,7 +1789,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_c14 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1805,7 +1805,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_c15 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1821,7 +1821,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_d0 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1837,7 +1837,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_d1 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1853,7 +1853,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_d2 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1869,7 +1869,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_d3 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1885,7 +1885,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_d4 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1901,7 +1901,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_d5 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1917,7 +1917,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_d6 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1933,7 +1933,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_d7 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1949,7 +1949,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_d8 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1965,7 +1965,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_d9 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1981,7 +1981,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_d10 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -1997,7 +1997,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_d11 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -2013,7 +2013,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_d12 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -2029,7 +2029,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_d13 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -2045,7 +2045,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_d14 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -2061,7 +2061,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@non_dead_d15 ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -2133,7 +2133,7 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@useless_arg_sink ; NOT_CGSCC_NPM-SAME: () #[[ATTR11]] { -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn @@ -2206,7 +2206,7 @@ ; NOT_CGSCC_NPM-NEXT: i64 10, label [[RETURN]] ; NOT_CGSCC_NPM-NEXT: ] ; NOT_CGSCC_NPM: sw.default: -; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR14]] +; NOT_CGSCC_NPM-NEXT: call void @sink() #[[ATTR15]] ; NOT_CGSCC_NPM-NEXT: ret i32 undef ; NOT_CGSCC_NPM: return: ; NOT_CGSCC_NPM-NEXT: unreachable @@ -2399,12 +2399,20 @@ } ; FIXME: Figure out why the MODULE has the unused arguments still define internal void @called_via_pointer_internal_2(i32* %a, i32* %b, i32* %c, i64 %d, i32** %e) { -; CHECK-LABEL: define {{[^@]+}}@called_via_pointer_internal_2 -; CHECK-SAME: (i32* [[A:%.*]], i32* nocapture nofree readnone [[B:%.*]], i32* nocapture nofree readnone [[C:%.*]], i64 [[D:%.*]], i32** nocapture nofree readnone [[E:%.*]]) { -; CHECK-NEXT: entry: -; CHECK-NEXT: tail call void @use_i32p(i32* [[A]]) -; CHECK-NEXT: tail call void @use_i32p(i32* [[A]]) -; CHECK-NEXT: ret void +; NOT_CGSCC_NPM: Function Attrs: norecurse +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@called_via_pointer_internal_2 +; NOT_CGSCC_NPM-SAME: (i32* [[A:%.*]], i32* nocapture nofree readnone [[B:%.*]], i32* nocapture nofree readnone [[C:%.*]], i64 [[D:%.*]], i32** nocapture nofree readnone [[E:%.*]]) #[[ATTR13:[0-9]+]] { +; NOT_CGSCC_NPM-NEXT: entry: +; NOT_CGSCC_NPM-NEXT: tail call void @use_i32p(i32* [[A]]) +; NOT_CGSCC_NPM-NEXT: tail call void @use_i32p(i32* [[A]]) +; NOT_CGSCC_NPM-NEXT: ret void +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@called_via_pointer_internal_2 +; IS__CGSCC____-SAME: (i32* [[A:%.*]], i32* nocapture nofree readnone [[B:%.*]], i32* nocapture nofree readnone [[C:%.*]], i64 [[D:%.*]], i32** nocapture nofree readnone [[E:%.*]]) { +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: tail call void @use_i32p(i32* [[A]]) +; IS__CGSCC____-NEXT: tail call void @use_i32p(i32* [[A]]) +; IS__CGSCC____-NEXT: ret void ; entry: tail call void @use_i32p(i32* %a) @@ -2563,7 +2571,7 @@ ; NOT_CGSCC_NPM-NEXT: entry: ; NOT_CGSCC_NPM-NEXT: [[N:%.*]] = alloca i8, align 1 ; NOT_CGSCC_NPM-NEXT: [[M:%.*]] = alloca i8, align 1 -; NOT_CGSCC_NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 1, i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[N]]) #[[ATTR15:[0-9]+]] +; NOT_CGSCC_NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 1, i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[N]]) #[[ATTR16:[0-9]+]] ; NOT_CGSCC_NPM-NEXT: br label [[EXIT:%.*]] ; NOT_CGSCC_NPM: while.body: ; NOT_CGSCC_NPM-NEXT: unreachable @@ -2572,7 +2580,7 @@ ; NOT_CGSCC_NPM: if.end: ; NOT_CGSCC_NPM-NEXT: unreachable ; NOT_CGSCC_NPM: exit: -; NOT_CGSCC_NPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 1, i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[N]]) #[[ATTR15]] +; NOT_CGSCC_NPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 1, i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[N]]) #[[ATTR16]] ; NOT_CGSCC_NPM-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn @@ -2637,9 +2645,10 @@ ; NOT_CGSCC_NPM: attributes #[[ATTR10]] = { nofree noreturn nosync nounwind readnone willreturn } ; NOT_CGSCC_NPM: attributes #[[ATTR11]] = { nofree nosync nounwind willreturn } ; NOT_CGSCC_NPM: attributes #[[ATTR12]] = { nofree nosync nounwind readnone willreturn } -; NOT_CGSCC_NPM: attributes #[[ATTR13:[0-9]+]] = { argmemonly nofree nosync nounwind willreturn } -; NOT_CGSCC_NPM: attributes #[[ATTR14]] = { nounwind willreturn } -; NOT_CGSCC_NPM: attributes #[[ATTR15]] = { willreturn } +; NOT_CGSCC_NPM: attributes #[[ATTR13]] = { norecurse } +; NOT_CGSCC_NPM: attributes #[[ATTR14:[0-9]+]] = { argmemonly nofree nosync nounwind willreturn } +; NOT_CGSCC_NPM: attributes #[[ATTR15]] = { nounwind willreturn } +; NOT_CGSCC_NPM: attributes #[[ATTR16]] = { willreturn } ;. ; IS__CGSCC____: attributes #[[ATTR0]] = { nofree noreturn nosync nounwind } ; IS__CGSCC____: attributes #[[ATTR1:[0-9]+]] = { readnone } diff --git a/llvm/test/Transforms/Attributor/memory_locations.ll b/llvm/test/Transforms/Attributor/memory_locations.ll --- a/llvm/test/Transforms/Attributor/memory_locations.ll +++ b/llvm/test/Transforms/Attributor/memory_locations.ll @@ -524,7 +524,7 @@ ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@writeonly_global_via_arg_internal ; IS__CGSCC____-SAME: () #[[ATTR6]] { -; IS__CGSCC____-NEXT: call void @write_global_via_arg_internal() #[[ATTR10]] +; IS__CGSCC____-NEXT: call void @write_global_via_arg_internal() #[[ATTR11:[0-9]+]] ; IS__CGSCC____-NEXT: ret void ; call void @write_global_via_arg_internal(i32* @G) @@ -550,7 +550,7 @@ ; IS__CGSCC____-NEXT: [[ALLOC:%.*]] = alloca i8, align 1 ; IS__CGSCC____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] ; IS__CGSCC____: t: -; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i8 @recursive_not_readnone(i8* noalias nocapture nofree noundef nonnull writeonly dereferenceable(1) [[ALLOC]], i1 noundef false) #[[ATTR11:[0-9]+]] +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i8 @recursive_not_readnone(i8* noalias nocapture nofree noundef nonnull writeonly dereferenceable(1) [[ALLOC]], i1 noundef false) #[[ATTR12:[0-9]+]] ; IS__CGSCC____-NEXT: ret i8 1 ; IS__CGSCC____: f: ; IS__CGSCC____-NEXT: store i8 1, i8* [[PTR]], align 1 @@ -586,7 +586,7 @@ ; IS__CGSCC____-NEXT: [[ALLOC:%.*]] = alloca i8, align 1 ; IS__CGSCC____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] ; IS__CGSCC____: t: -; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i8 @recursive_not_readnone_internal(i8* noalias nocapture nofree noundef nonnull writeonly dereferenceable(1) [[ALLOC]], i1 noundef false) #[[ATTR11]], !range [[RNG0:![0-9]+]] +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i8 @recursive_not_readnone_internal(i8* noalias nocapture nofree noundef nonnull writeonly dereferenceable(1) [[ALLOC]], i1 noundef false) #[[ATTR12]], !range [[RNG0:![0-9]+]] ; IS__CGSCC____-NEXT: ret i8 1 ; IS__CGSCC____: f: ; IS__CGSCC____-NEXT: store i8 1, i8* [[PTR]], align 1 @@ -615,7 +615,7 @@ ; IS__CGSCC____-LABEL: define {{[^@]+}}@readnone_caller ; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR9:[0-9]+]] { ; IS__CGSCC____-NEXT: [[A:%.*]] = alloca i8, align 1 -; IS__CGSCC____-NEXT: [[R:%.*]] = call noundef i8 @recursive_not_readnone_internal(i8* noalias nocapture nofree noundef nonnull writeonly dereferenceable(1) [[A]], i1 [[C]]) #[[ATTR12:[0-9]+]], !range [[RNG0]] +; IS__CGSCC____-NEXT: [[R:%.*]] = call noundef i8 @recursive_not_readnone_internal(i8* noalias nocapture nofree noundef nonnull writeonly dereferenceable(1) [[A]], i1 [[C]]) #[[ATTR13:[0-9]+]], !range [[RNG0]] ; IS__CGSCC____-NEXT: ret i8 [[R]] ; %a = alloca i8 @@ -642,7 +642,7 @@ ; IS__CGSCC____-NEXT: [[ALLOC:%.*]] = alloca i8, align 1 ; IS__CGSCC____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] ; IS__CGSCC____: t: -; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i8 @recursive_readnone_internal2(i8* noalias nocapture nofree noundef nonnull writeonly dereferenceable(1) [[ALLOC]], i1 noundef false) #[[ATTR11]], !range [[RNG0]] +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i8 @recursive_readnone_internal2(i8* noalias nocapture nofree noundef nonnull writeonly dereferenceable(1) [[ALLOC]], i1 noundef false) #[[ATTR12]], !range [[RNG0]] ; IS__CGSCC____-NEXT: ret i8 1 ; IS__CGSCC____: f: ; IS__CGSCC____-NEXT: store i8 1, i8* [[PTR]], align 1 @@ -669,7 +669,7 @@ ; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone ; IS__CGSCC____-LABEL: define {{[^@]+}}@readnone_caller2 ; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR9]] { -; IS__CGSCC____-NEXT: [[R:%.*]] = call noundef i8 @recursive_readnone_internal2(i8* undef, i1 [[C]]) #[[ATTR12]], !range [[RNG0]] +; IS__CGSCC____-NEXT: [[R:%.*]] = call noundef i8 @recursive_readnone_internal2(i8* undef, i1 [[C]]) #[[ATTR13]], !range [[RNG0]] ; IS__CGSCC____-NEXT: ret i8 [[R]] ; %r = call i8 @recursive_readnone_internal2(i8* undef, i1 %c) @@ -695,7 +695,7 @@ ; IS__CGSCC____-NEXT: [[ALLOC:%.*]] = alloca i8, align 1 ; IS__CGSCC____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] ; IS__CGSCC____: t: -; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i8 @recursive_not_readnone_internal3(i8* noalias nocapture nofree noundef nonnull writeonly dereferenceable(1) [[ALLOC]], i1 noundef false) #[[ATTR11]], !range [[RNG0]] +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i8 @recursive_not_readnone_internal3(i8* noalias nocapture nofree noundef nonnull writeonly dereferenceable(1) [[ALLOC]], i1 noundef false) #[[ATTR12]], !range [[RNG0]] ; IS__CGSCC____-NEXT: ret i8 1 ; IS__CGSCC____: f: ; IS__CGSCC____-NEXT: store i8 1, i8* [[PTR]], align 1 @@ -724,7 +724,7 @@ ; IS__CGSCC____-LABEL: define {{[^@]+}}@readnone_caller3 ; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR9]] { ; IS__CGSCC____-NEXT: [[ALLOC:%.*]] = alloca i8, align 1 -; IS__CGSCC____-NEXT: [[R:%.*]] = call noundef i8 @recursive_not_readnone_internal3(i8* noalias nocapture nofree noundef nonnull writeonly dereferenceable(1) [[ALLOC]], i1 [[C]]) #[[ATTR12]], !range [[RNG0]] +; IS__CGSCC____-NEXT: [[R:%.*]] = call noundef i8 @recursive_not_readnone_internal3(i8* noalias nocapture nofree noundef nonnull writeonly dereferenceable(1) [[ALLOC]], i1 [[C]]) #[[ATTR13]], !range [[RNG0]] ; IS__CGSCC____-NEXT: ret i8 [[R]] ; %alloc = alloca i8 @@ -733,12 +733,6 @@ } define internal void @argmemonly_before_ipconstprop(i32* %p) argmemonly { -; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly -; IS__TUNIT____-LABEL: define {{[^@]+}}@argmemonly_before_ipconstprop -; IS__TUNIT____-SAME: () #[[ATTR6]] { -; IS__TUNIT____-NEXT: store i32 0, i32* @G, align 4 -; IS__TUNIT____-NEXT: ret void -; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@argmemonly_before_ipconstprop ; IS__CGSCC____-SAME: () #[[ATTR6]] { @@ -750,16 +744,14 @@ } define void @argmemonky_caller() { -; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@argmemonky_caller -; IS__TUNIT____-SAME: () #[[ATTR6]] { -; IS__TUNIT____-NEXT: call void @argmemonly_before_ipconstprop() #[[ATTR6]] +; IS__TUNIT____-SAME: () #[[ATTR5]] { ; IS__TUNIT____-NEXT: ret void ; -; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@argmemonky_caller -; IS__CGSCC____-SAME: () #[[ATTR6]] { -; IS__CGSCC____-NEXT: call void @argmemonly_before_ipconstprop() #[[ATTR10]] +; IS__CGSCC____-SAME: () #[[ATTR5]] { ; IS__CGSCC____-NEXT: ret void ; call void @argmemonly_before_ipconstprop(i32* @G) @@ -789,8 +781,9 @@ ; IS__CGSCC____: attributes #[[ATTR8]] = { argmemonly nofree nosync nounwind writeonly } ; IS__CGSCC____: attributes #[[ATTR9]] = { nofree nosync nounwind readnone } ; IS__CGSCC____: attributes #[[ATTR10]] = { nounwind willreturn writeonly } -; IS__CGSCC____: attributes #[[ATTR11]] = { nofree nosync nounwind writeonly } -; IS__CGSCC____: attributes #[[ATTR12]] = { nounwind writeonly } +; IS__CGSCC____: attributes #[[ATTR11]] = { norecurse nounwind willreturn writeonly } +; IS__CGSCC____: attributes #[[ATTR12]] = { nofree nosync nounwind writeonly } +; IS__CGSCC____: attributes #[[ATTR13]] = { nounwind writeonly } ;. ; CHECK: [[META0:![0-9]+]] = !{i8 0, i8 2} ;. diff --git a/llvm/test/Transforms/Attributor/misc.ll b/llvm/test/Transforms/Attributor/misc.ll --- a/llvm/test/Transforms/Attributor/misc.ll +++ b/llvm/test/Transforms/Attributor/misc.ll @@ -121,5 +121,5 @@ ; IS__TUNIT____: attributes #[[ATTR1]] = { nofree nosync nounwind willreturn writeonly } ;. ; IS__CGSCC____: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly } -; IS__CGSCC____: attributes #[[ATTR1]] = { nounwind willreturn writeonly } +; IS__CGSCC____: attributes #[[ATTR1]] = { norecurse nounwind willreturn writeonly } ;. diff --git a/llvm/test/Transforms/Attributor/noalias.ll b/llvm/test/Transforms/Attributor/noalias.ll --- a/llvm/test/Transforms/Attributor/noalias.ll +++ b/llvm/test/Transforms/Attributor/noalias.ll @@ -812,7 +812,7 @@ ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@test16_caller ; IS__CGSCC____-SAME: (i32* nofree writeonly [[P:%.*]], i32 [[C:%.*]]) #[[ATTR7]] { -; IS__CGSCC____-NEXT: tail call void @test16_sub(i32* noalias nofree writeonly [[P]], i32 [[C]], i32 [[C]]) #[[ATTR13]] +; IS__CGSCC____-NEXT: tail call void @test16_sub(i32* noalias nofree writeonly [[P]], i32 [[C]], i32 [[C]]) #[[ATTR14:[0-9]+]] ; IS__CGSCC____-NEXT: ret void ; tail call void @test16_sub(i32* %p, i32 %c, i32 %c) @@ -974,8 +974,9 @@ ; IS__CGSCC____: attributes #[[ATTR7]] = { nofree norecurse nosync nounwind willreturn writeonly } ; IS__CGSCC____: attributes #[[ATTR8]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly } ; IS__CGSCC____: attributes #[[ATTR9]] = { nofree norecurse noreturn nosync nounwind readnone willreturn } -; IS__CGSCC____: attributes #[[ATTR10]] = { readnone willreturn } -; IS__CGSCC____: attributes #[[ATTR11]] = { readonly willreturn } +; IS__CGSCC____: attributes #[[ATTR10]] = { norecurse nounwind readnone willreturn } +; IS__CGSCC____: attributes #[[ATTR11]] = { norecurse nounwind readonly willreturn } ; IS__CGSCC____: attributes #[[ATTR12]] = { willreturn } ; IS__CGSCC____: attributes #[[ATTR13]] = { nounwind willreturn writeonly } +; IS__CGSCC____: attributes #[[ATTR14]] = { norecurse nounwind willreturn writeonly } ;. diff --git a/llvm/test/Transforms/Attributor/nodelete.ll b/llvm/test/Transforms/Attributor/nodelete.ll --- a/llvm/test/Transforms/Attributor/nodelete.ll +++ b/llvm/test/Transforms/Attributor/nodelete.ll @@ -32,6 +32,8 @@ ; IS__CGSCC____-LABEL: define {{[^@]+}}@f2 ; IS__CGSCC____-SAME: () #[[ATTR0]] align 2 { ; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[THIS_ADDR:%.*]] = alloca %a*, align 8 +; IS__CGSCC____-NEXT: [[THIS1:%.*]] = load %a*, %a** [[THIS_ADDR]], align 8 ; IS__CGSCC____-NEXT: ret i64 undef ; entry: diff --git a/llvm/test/Transforms/Attributor/norecurse.ll b/llvm/test/Transforms/Attributor/norecurse.ll --- a/llvm/test/Transforms/Attributor/norecurse.ll +++ b/llvm/test/Transforms/Attributor/norecurse.ll @@ -121,23 +121,17 @@ declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i1) define internal i32 @called_by_norecurse() { -; IS__TUNIT____: Function Attrs: nosync readnone -; IS__TUNIT____-LABEL: define {{[^@]+}}@called_by_norecurse -; IS__TUNIT____-SAME: () #[[ATTR2]] { -; IS__TUNIT____-NEXT: [[A:%.*]] = call i32 @k() -; IS__TUNIT____-NEXT: ret i32 undef +; NOT_CGSCC_OPM: Function Attrs: norecurse nosync readnone +; NOT_CGSCC_OPM-LABEL: define {{[^@]+}}@called_by_norecurse +; NOT_CGSCC_OPM-SAME: () #[[ATTR6:[0-9]+]] { +; NOT_CGSCC_OPM-NEXT: [[A:%.*]] = call i32 @k() +; NOT_CGSCC_OPM-NEXT: ret i32 undef ; ; IS__CGSCC_OPM: Function Attrs: norecurse nosync readnone ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@called_by_norecurse ; IS__CGSCC_OPM-SAME: () #[[ATTR7:[0-9]+]] { ; IS__CGSCC_OPM-NEXT: [[A:%.*]] = call i32 @k() ; IS__CGSCC_OPM-NEXT: ret i32 undef -; -; IS__CGSCC_NPM: Function Attrs: norecurse nosync readnone -; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@called_by_norecurse -; IS__CGSCC_NPM-SAME: () #[[ATTR6:[0-9]+]] { -; IS__CGSCC_NPM-NEXT: [[A:%.*]] = call i32 @k() -; IS__CGSCC_NPM-NEXT: ret i32 undef ; %a = call i32 @k() ret i32 %a @@ -145,7 +139,7 @@ define void @m() norecurse { ; IS__TUNIT____: Function Attrs: norecurse nosync readnone ; IS__TUNIT____-LABEL: define {{[^@]+}}@m -; IS__TUNIT____-SAME: () #[[ATTR6:[0-9]+]] { +; IS__TUNIT____-SAME: () #[[ATTR6]] { ; IS__TUNIT____-NEXT: [[A:%.*]] = call i32 @called_by_norecurse() #[[ATTR2]] ; IS__TUNIT____-NEXT: ret void ; @@ -166,15 +160,15 @@ } define internal i32 @called_by_norecurse_indirectly() { -; NOT_CGSCC_OPM: Function Attrs: nosync readnone +; NOT_CGSCC_OPM: Function Attrs: norecurse nosync readnone ; NOT_CGSCC_OPM-LABEL: define {{[^@]+}}@called_by_norecurse_indirectly -; NOT_CGSCC_OPM-SAME: () #[[ATTR2]] { +; NOT_CGSCC_OPM-SAME: () #[[ATTR6]] { ; NOT_CGSCC_OPM-NEXT: [[A:%.*]] = call i32 @k() ; NOT_CGSCC_OPM-NEXT: ret i32 [[A]] ; -; IS__CGSCC_OPM: Function Attrs: nosync readnone +; IS__CGSCC_OPM: Function Attrs: norecurse nosync readnone ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@called_by_norecurse_indirectly -; IS__CGSCC_OPM-SAME: () #[[ATTR3]] { +; IS__CGSCC_OPM-SAME: () #[[ATTR7]] { ; IS__CGSCC_OPM-NEXT: [[A:%.*]] = call i32 @k() ; IS__CGSCC_OPM-NEXT: ret i32 [[A]] ; @@ -182,9 +176,9 @@ ret i32 %a } define internal i32 @o() { -; IS__TUNIT____: Function Attrs: nosync readnone +; IS__TUNIT____: Function Attrs: norecurse nosync readnone ; IS__TUNIT____-LABEL: define {{[^@]+}}@o -; IS__TUNIT____-SAME: () #[[ATTR2]] { +; IS__TUNIT____-SAME: () #[[ATTR6]] { ; IS__TUNIT____-NEXT: [[A:%.*]] = call i32 @called_by_norecurse_indirectly() #[[ATTR2]] ; IS__TUNIT____-NEXT: ret i32 [[A]] ; diff --git a/llvm/test/Transforms/Attributor/potential.ll b/llvm/test/Transforms/Attributor/potential.ll --- a/llvm/test/Transforms/Attributor/potential.ll +++ b/llvm/test/Transforms/Attributor/potential.ll @@ -60,6 +60,7 @@ ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@call_with_two_values ; IS__CGSCC____-SAME: () #[[ATTR0]] { +; IS__CGSCC____-NEXT: [[RET:%.*]] = add i32 0, 0 ; IS__CGSCC____-NEXT: ret i32 undef ; %csret1 = call i32 @iszero2(i32 %c) @@ -113,10 +114,8 @@ define internal i32 @less_than_two(i32 %c) { ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@less_than_two -; IS__CGSCC____-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { -; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp slt i32 undef, 2 -; IS__CGSCC____-NEXT: [[RET:%.*]] = zext i1 true to i32 -; IS__CGSCC____-NEXT: ret i32 1 +; IS__CGSCC____-SAME: () #[[ATTR0]] { +; IS__CGSCC____-NEXT: ret i32 undef ; %cmp = icmp slt i32 %c, 2 %ret = zext i1 %cmp to i32 @@ -228,7 +227,7 @@ ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test7 ; IS__CGSCC_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { ; IS__CGSCC_OPM-NEXT: [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR2]], !range [[RNG0]] -; IS__CGSCC_OPM-NEXT: [[CSRET2:%.*]] = call i32 @return3or4(i32 [[C]]) #[[ATTR2]], !range [[RNG1:![0-9]+]] +; IS__CGSCC_OPM-NEXT: [[CSRET2:%.*]] = call i32 @return3or4(i32 [[C]]) #[[ATTR3:[0-9]+]], !range [[RNG1:![0-9]+]] ; IS__CGSCC_OPM-NEXT: [[RET:%.*]] = icmp eq i32 [[CSRET1]], [[CSRET2]] ; IS__CGSCC_OPM-NEXT: ret i1 [[RET]] ; @@ -236,7 +235,7 @@ ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test7 ; IS__CGSCC_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR0]] { ; IS__CGSCC_NPM-NEXT: [[CSRET1:%.*]] = call i32 @return1or3(i32 [[C]]) #[[ATTR1]], !range [[RNG0]] -; IS__CGSCC_NPM-NEXT: [[CSRET2:%.*]] = call i32 @return3or4(i32 [[C]]) #[[ATTR1]], !range [[RNG1:![0-9]+]] +; IS__CGSCC_NPM-NEXT: [[CSRET2:%.*]] = call i32 @return3or4(i32 [[C]]) #[[ATTR2:[0-9]+]], !range [[RNG1:![0-9]+]] ; IS__CGSCC_NPM-NEXT: [[RET:%.*]] = icmp eq i32 [[CSRET1]], [[CSRET2]] ; IS__CGSCC_NPM-NEXT: ret i1 [[RET]] ; @@ -757,13 +756,13 @@ ; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test13_caller3 ; IS__CGSCC_OPM-SAME: () #[[ATTR0]] { -; IS__CGSCC_OPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 undef) #[[ATTR2]], !range [[RNG2]] +; IS__CGSCC_OPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 undef) #[[ATTR3]], !range [[RNG2]] ; IS__CGSCC_OPM-NEXT: ret i32 [[RET]] ; ; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@potential_test13_caller3 ; IS__CGSCC_NPM-SAME: () #[[ATTR0]] { -; IS__CGSCC_NPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 undef) #[[ATTR1]], !range [[RNG2]] +; IS__CGSCC_NPM-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 undef) #[[ATTR2]], !range [[RNG2]] ; IS__CGSCC_NPM-NEXT: ret i32 [[RET]] ; %ret = call i32 @potential_test13_callee(i32 undef) @@ -842,9 +841,11 @@ ; IS__CGSCC_OPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } ; IS__CGSCC_OPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone } ; IS__CGSCC_OPM: attributes #[[ATTR2]] = { readnone willreturn } +; IS__CGSCC_OPM: attributes #[[ATTR3]] = { norecurse nounwind readnone willreturn } ;. ; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } ; IS__CGSCC_NPM: attributes #[[ATTR1]] = { readnone willreturn } +; IS__CGSCC_NPM: attributes #[[ATTR2]] = { norecurse nounwind readnone willreturn } ;. ; CHECK: [[META0:![0-9]+]] = !{i32 1, i32 4} ; CHECK: [[META1:![0-9]+]] = !{i32 3, i32 5} diff --git a/llvm/test/Transforms/Attributor/range.ll b/llvm/test/Transforms/Attributor/range.ll --- a/llvm/test/Transforms/Attributor/range.ll +++ b/llvm/test/Transforms/Attributor/range.ll @@ -1518,9 +1518,8 @@ define internal i1 @is_less_than_65536(i32 %arg) { ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@is_less_than_65536 -; IS__CGSCC____-SAME: (i32 [[ARG:%.*]]) #[[ATTR1]] { -; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp ult i32 undef, 65536 -; IS__CGSCC____-NEXT: ret i1 true +; IS__CGSCC____-SAME: () #[[ATTR1]] { +; IS__CGSCC____-NEXT: ret i1 undef ; %cmp = icmp ult i32 %arg, 65536 ret i1 %cmp @@ -1726,9 +1725,8 @@ ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@is_less_than_100_2 -; IS__CGSCC____-SAME: (i32 [[C:%.*]]) #[[ATTR1]] { -; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp slt i32 undef, 100 -; IS__CGSCC____-NEXT: ret i1 true +; IS__CGSCC____-SAME: () #[[ATTR1]] { +; IS__CGSCC____-NEXT: ret i1 undef ; %cmp = icmp slt i32 %c, 100 ret i1 %cmp @@ -1807,7 +1805,7 @@ ; IS__CGSCC_OPM-NEXT: [[C:%.*]] = icmp slt i8 0, [[L]] ; IS__CGSCC_OPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] ; IS__CGSCC_OPM: t: -; IS__CGSCC_OPM-NEXT: [[R:%.*]] = call i1 @non_zero(i8 [[L]]) #[[ATTR5]] +; IS__CGSCC_OPM-NEXT: [[R:%.*]] = call i1 @non_zero(i8 [[L]]) #[[ATTR6:[0-9]+]] ; IS__CGSCC_OPM-NEXT: ret i1 [[R]] ; IS__CGSCC_OPM: f: ; IS__CGSCC_OPM-NEXT: ret i1 false @@ -1919,6 +1917,7 @@ ; IS__CGSCC_OPM: attributes #[[ATTR3]] = { readonly willreturn } ; IS__CGSCC_OPM: attributes #[[ATTR4]] = { nounwind readnone } ; IS__CGSCC_OPM: attributes #[[ATTR5]] = { readnone willreturn } +; IS__CGSCC_OPM: attributes #[[ATTR6]] = { norecurse nounwind readnone willreturn } ;. ; IS__CGSCC_NPM: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind readonly willreturn } ; IS__CGSCC_NPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn } diff --git a/llvm/test/Transforms/Attributor/value-simplify-pointer-info-gpu.ll b/llvm/test/Transforms/Attributor/value-simplify-pointer-info-gpu.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/Attributor/value-simplify-pointer-info-gpu.ll @@ -0,0 +1,462 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals +; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=15 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM +; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=15 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM +; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM +; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM + +target triple = "amdgcn-amd-amdhsa" + +@ReachableKernel = internal addrspace(3) global i32 0, align 4 +@UnreachableKernel = internal addrspace(3) global i32 0, align 4 +@ReachableKernelAS0 = internal global i32 0, align 4 + +;. +; CHECK: @[[REACHABLEKERNEL:[a-zA-Z0-9_$"\\.-]+]] = internal addrspace(3) global i32 0, align 4 +; CHECK: @[[UNREACHABLEKERNEL:[a-zA-Z0-9_$"\\.-]+]] = internal addrspace(3) global i32 0, align 4 +; CHECK: @[[REACHABLEKERNELAS0:[a-zA-Z0-9_$"\\.-]+]] = internal global i32 0, align 4 +; CHECK: @[[REACHABLENONKERNEL:[a-zA-Z0-9_$"\\.-]+]] = internal addrspace(3) global i32 0, align 4 +; CHECK: @[[UNREACHABLENONKERNEL:[a-zA-Z0-9_$"\\.-]+]] = internal addrspace(3) global i32 0, align 4 +;. +define dso_local void @kernel(i32 %C) norecurse "kernel" { +; IS__TUNIT____: Function Attrs: norecurse nosync nounwind +; IS__TUNIT____-LABEL: define {{[^@]+}}@kernel +; IS__TUNIT____-SAME: (i32 [[C:%.*]]) #[[ATTR0:[0-9]+]] { +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: call void @level1Kernel(i32 [[C]]) #[[ATTR1:[0-9]+]] +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: norecurse nosync nounwind +; IS__CGSCC____-LABEL: define {{[^@]+}}@kernel +; IS__CGSCC____-SAME: (i32 [[C:%.*]]) #[[ATTR0:[0-9]+]] { +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: call void @level1Kernel(i32 [[C]]) #[[ATTR4:[0-9]+]] +; IS__CGSCC____-NEXT: ret void +; +entry: + call void @level1Kernel(i32 %C) + ret void +} + +define internal void @level1Kernel(i32 %C) { +; IS__TUNIT____: Function Attrs: norecurse nosync nounwind +; IS__TUNIT____-LABEL: define {{[^@]+}}@level1Kernel +; IS__TUNIT____-SAME: (i32 [[C:%.*]]) #[[ATTR1]] { +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: call void @level2Kernelall_early() #[[ATTR3:[0-9]+]] +; IS__TUNIT____-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[C]], 0 +; IS__TUNIT____-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; IS__TUNIT____: if.then: +; IS__TUNIT____-NEXT: call void @level2Kernela() #[[ATTR4:[0-9]+]] +; IS__TUNIT____-NEXT: br label [[IF_END:%.*]] +; IS__TUNIT____: if.else: +; IS__TUNIT____-NEXT: call void @level2Kernelb() #[[ATTR4]] +; IS__TUNIT____-NEXT: br label [[IF_END]] +; IS__TUNIT____: if.end: +; IS__TUNIT____-NEXT: call void @level2Kernelall_late() #[[ATTR5:[0-9]+]] +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: norecurse nosync nounwind +; IS__CGSCC____-LABEL: define {{[^@]+}}@level1Kernel +; IS__CGSCC____-SAME: (i32 [[C:%.*]]) #[[ATTR1:[0-9]+]] { +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: call void @level2Kernelall_early() #[[ATTR5:[0-9]+]] +; IS__CGSCC____-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[C]], 0 +; IS__CGSCC____-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; IS__CGSCC____: if.then: +; IS__CGSCC____-NEXT: call void @level2Kernela() #[[ATTR4]] +; IS__CGSCC____-NEXT: br label [[IF_END:%.*]] +; IS__CGSCC____: if.else: +; IS__CGSCC____-NEXT: call void @level2Kernelb() #[[ATTR4]] +; IS__CGSCC____-NEXT: br label [[IF_END]] +; IS__CGSCC____: if.end: +; IS__CGSCC____-NEXT: call void @level2Kernelall_late() #[[ATTR6:[0-9]+]] +; IS__CGSCC____-NEXT: ret void +; +entry: + call void @level2Kernelall_early() + %tobool = icmp ne i32 %C, 0 + br i1 %tobool, label %if.then, label %if.else + +if.then: ; preds = %entry + call void @level2Kernela() + br label %if.end + +if.else: ; preds = %entry + call void @level2Kernelb() + br label %if.end + +if.end: ; preds = %if.else, %if.then + call void @level2Kernelall_late() + ret void +} + +define internal void @level2Kernelall_early() { +; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly +; CHECK-LABEL: define {{[^@]+}}@level2Kernelall_early +; CHECK-SAME: () #[[ATTR2:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: store i32 1, i32* @ReachableKernelAS0, align 4 +; CHECK-NEXT: store i32 1, i32* addrspacecast (i32 addrspace(3)* @ReachableKernel to i32*), align 4 +; CHECK-NEXT: ret void +; +entry: + store i32 1, i32* @ReachableKernelAS0, align 4 + store i32 1, i32* addrspacecast (i32 addrspace(3)* @ReachableKernel to i32*), align 4 + ret void +} + +define internal void @level2Kernela() { +; IS__TUNIT____: Function Attrs: norecurse nosync nounwind +; IS__TUNIT____-LABEL: define {{[^@]+}}@level2Kernela +; IS__TUNIT____-SAME: () #[[ATTR1]] { +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[TMP0:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @ReachableKernel to i32*), align 4 +; IS__TUNIT____-NEXT: [[TMP1:%.*]] = load i32, i32* @ReachableKernelAS0, align 4 +; IS__TUNIT____-NEXT: call void @use(i32 [[TMP0]], i32 [[TMP1]], i32 noundef 0) #[[ATTR6:[0-9]+]] +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: norecurse nosync nounwind +; IS__CGSCC____-LABEL: define {{[^@]+}}@level2Kernela +; IS__CGSCC____-SAME: () #[[ATTR1]] { +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @ReachableKernel to i32*), align 4 +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = load i32, i32* @ReachableKernelAS0, align 4 +; IS__CGSCC____-NEXT: [[TMP2:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @UnreachableKernel to i32*), align 4 +; IS__CGSCC____-NEXT: call void @use(i32 [[TMP0]], i32 [[TMP1]], i32 0) #[[ATTR4]] +; IS__CGSCC____-NEXT: ret void +; +entry: + %0 = load i32, i32* addrspacecast (i32 addrspace(3)* @ReachableKernel to i32*), align 4 + %1 = load i32, i32* @ReachableKernelAS0, align 4 + %2 = load i32, i32* addrspacecast (i32 addrspace(3)* @UnreachableKernel to i32*), align 4 + call void @use(i32 %0, i32 %1, i32 %2) + ret void +} + +define internal void @level2Kernelb() { +; IS__TUNIT____: Function Attrs: norecurse nosync nounwind +; IS__TUNIT____-LABEL: define {{[^@]+}}@level2Kernelb +; IS__TUNIT____-SAME: () #[[ATTR1]] { +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[TMP0:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @ReachableKernel to i32*), align 4 +; IS__TUNIT____-NEXT: [[TMP1:%.*]] = load i32, i32* @ReachableKernelAS0, align 4 +; IS__TUNIT____-NEXT: call void @use(i32 [[TMP0]], i32 [[TMP1]], i32 noundef 0) #[[ATTR6]] +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: norecurse nosync nounwind +; IS__CGSCC____-LABEL: define {{[^@]+}}@level2Kernelb +; IS__CGSCC____-SAME: () #[[ATTR1]] { +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @ReachableKernel to i32*), align 4 +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = load i32, i32* @ReachableKernelAS0, align 4 +; IS__CGSCC____-NEXT: [[TMP2:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @UnreachableKernel to i32*), align 4 +; IS__CGSCC____-NEXT: call void @use(i32 [[TMP0]], i32 [[TMP1]], i32 0) #[[ATTR4]] +; IS__CGSCC____-NEXT: ret void +; +entry: + %0 = load i32, i32* addrspacecast (i32 addrspace(3)* @ReachableKernel to i32*), align 4 + %1 = load i32, i32* @ReachableKernelAS0, align 4 + %2 = load i32, i32* addrspacecast (i32 addrspace(3)* @UnreachableKernel to i32*), align 4 + call void @use(i32 %0, i32 %1, i32 %2) + ret void +} + +define internal void @level2Kernelall_late() { +; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@level2Kernelall_late +; IS__TUNIT____-SAME: () #[[ATTR2]] { +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@level2Kernelall_late +; IS__CGSCC____-SAME: () #[[ATTR3:[0-9]+]] { +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: ret void +; +entry: + store i32 1, i32 *addrspacecast (i32 addrspace(3)* @UnreachableKernel to i32*), align 4 + ret void +} + +@ReachableNonKernel = internal addrspace(3) global i32 0, align 4 +@UnreachableNonKernel = internal addrspace(3) global i32 0, align 4 + +define dso_local void @non_kernel(i32 %C) norecurse { +; IS__TUNIT____: Function Attrs: norecurse nosync nounwind +; IS__TUNIT____-LABEL: define {{[^@]+}}@non_kernel +; IS__TUNIT____-SAME: (i32 [[C:%.*]]) #[[ATTR1]] { +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: call void @level1(i32 [[C]]) #[[ATTR1]] +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: norecurse nosync nounwind +; IS__CGSCC____-LABEL: define {{[^@]+}}@non_kernel +; IS__CGSCC____-SAME: (i32 [[C:%.*]]) #[[ATTR1]] { +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: call void @level1(i32 [[C]]) #[[ATTR4]] +; IS__CGSCC____-NEXT: ret void +; +entry: + call void @level1(i32 %C) + ret void +} + +define internal void @level1(i32 %C) { +; IS__TUNIT_OPM: Function Attrs: norecurse nosync nounwind +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@level1 +; IS__TUNIT_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR1]] { +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[LOCAL:%.*]] = alloca i32, align 4 +; IS__TUNIT_OPM-NEXT: call void @level2all_early(i32* noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[LOCAL]]) #[[ATTR3]] +; IS__TUNIT_OPM-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[C]], 0 +; IS__TUNIT_OPM-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; IS__TUNIT_OPM: if.then: +; IS__TUNIT_OPM-NEXT: call void @level2a(i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[LOCAL]]) #[[ATTR4]] +; IS__TUNIT_OPM-NEXT: br label [[IF_END:%.*]] +; IS__TUNIT_OPM: if.else: +; IS__TUNIT_OPM-NEXT: call void @level2b(i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[LOCAL]]) #[[ATTR4]] +; IS__TUNIT_OPM-NEXT: br label [[IF_END]] +; IS__TUNIT_OPM: if.end: +; IS__TUNIT_OPM-NEXT: call void @level2all_late(i32* noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[LOCAL]]) #[[ATTR5]] +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM: Function Attrs: norecurse nosync nounwind +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@level1 +; IS__TUNIT_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR1]] { +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[LOCAL:%.*]] = alloca i32, align 4 +; IS__TUNIT_NPM-NEXT: call void @level2all_early(i32* noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[LOCAL]]) #[[ATTR3]] +; IS__TUNIT_NPM-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[C]], 0 +; IS__TUNIT_NPM-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; IS__TUNIT_NPM: if.then: +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[LOCAL]], align 4 +; IS__TUNIT_NPM-NEXT: call void @level2a(i32 [[TMP0]]) #[[ATTR4]] +; IS__TUNIT_NPM-NEXT: br label [[IF_END:%.*]] +; IS__TUNIT_NPM: if.else: +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[LOCAL]], align 4 +; IS__TUNIT_NPM-NEXT: call void @level2b(i32 [[TMP1]]) #[[ATTR4]] +; IS__TUNIT_NPM-NEXT: br label [[IF_END]] +; IS__TUNIT_NPM: if.end: +; IS__TUNIT_NPM-NEXT: call void @level2all_late(i32* noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[LOCAL]]) #[[ATTR5]] +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM: Function Attrs: norecurse nosync nounwind +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@level1 +; IS__CGSCC_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR1]] { +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: [[LOCAL:%.*]] = alloca i32, align 4 +; IS__CGSCC_OPM-NEXT: call void @level2all_early(i32* noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[LOCAL]]) #[[ATTR5]] +; IS__CGSCC_OPM-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[C]], 0 +; IS__CGSCC_OPM-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; IS__CGSCC_OPM: if.then: +; IS__CGSCC_OPM-NEXT: call void @level2a(i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[LOCAL]]) #[[ATTR4]] +; IS__CGSCC_OPM-NEXT: br label [[IF_END:%.*]] +; IS__CGSCC_OPM: if.else: +; IS__CGSCC_OPM-NEXT: call void @level2b(i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[LOCAL]]) #[[ATTR4]] +; IS__CGSCC_OPM-NEXT: br label [[IF_END]] +; IS__CGSCC_OPM: if.end: +; IS__CGSCC_OPM-NEXT: call void @level2all_late(i32* noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[LOCAL]]) #[[ATTR7:[0-9]+]] +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM: Function Attrs: norecurse nosync nounwind +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@level1 +; IS__CGSCC_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR1]] { +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[LOCAL:%.*]] = alloca i32, align 4 +; IS__CGSCC_NPM-NEXT: call void @level2all_early(i32* noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[LOCAL]]) #[[ATTR5]] +; IS__CGSCC_NPM-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[C]], 0 +; IS__CGSCC_NPM-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; IS__CGSCC_NPM: if.then: +; IS__CGSCC_NPM-NEXT: call void @level2a(i32 undef) #[[ATTR4]] +; IS__CGSCC_NPM-NEXT: br label [[IF_END:%.*]] +; IS__CGSCC_NPM: if.else: +; IS__CGSCC_NPM-NEXT: call void @level2b(i32 undef) #[[ATTR7:[0-9]+]] +; IS__CGSCC_NPM-NEXT: br label [[IF_END]] +; IS__CGSCC_NPM: if.end: +; IS__CGSCC_NPM-NEXT: call void @level2all_late(i32* noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[LOCAL]]) #[[ATTR8:[0-9]+]] +; IS__CGSCC_NPM-NEXT: ret void +; +entry: + %local = alloca i32 + call void @level2all_early(i32* %local) + %tobool = icmp ne i32 %C, 0 + br i1 %tobool, label %if.then, label %if.else + +if.then: ; preds = %entry + call void @level2a(i32* %local) + br label %if.end + +if.else: ; preds = %entry + call void @level2b(i32* %local) + br label %if.end + +if.end: ; preds = %if.else, %if.then + call void @level2all_late(i32* %local) + ret void +} + +define internal void @level2all_early(i32* %addr) { +; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly +; CHECK-LABEL: define {{[^@]+}}@level2all_early +; CHECK-SAME: (i32* noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[ADDR:%.*]]) #[[ATTR2]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: store i32 1, i32* addrspacecast (i32 addrspace(3)* @ReachableNonKernel to i32*), align 4 +; CHECK-NEXT: store i32 3, i32* [[ADDR]], align 4 +; CHECK-NEXT: ret void +; +entry: + store i32 1, i32* addrspacecast (i32 addrspace(3)* @ReachableNonKernel to i32*), align 4 + store i32 3, i32* %addr, align 4 + ret void +} + +define internal void @level2a(i32* %addr) { +; IS__TUNIT_OPM: Function Attrs: norecurse nosync nounwind +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@level2a +; IS__TUNIT_OPM-SAME: (i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[ADDR:%.*]]) #[[ATTR1]] { +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @ReachableNonKernel to i32*), align 4 +; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @UnreachableNonKernel to i32*), align 4 +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[ADDR]], align 4 +; IS__TUNIT_OPM-NEXT: call void @use(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]]) #[[ATTR6]] +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM: Function Attrs: norecurse nosync nounwind +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@level2a +; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]]) #[[ATTR1]] { +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[ADDR_PRIV:%.*]] = alloca i32, align 4 +; IS__TUNIT_NPM-NEXT: store i32 [[TMP0]], i32* [[ADDR_PRIV]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @ReachableNonKernel to i32*), align 4 +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @UnreachableNonKernel to i32*), align 4 +; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[ADDR_PRIV]], align 4 +; IS__TUNIT_NPM-NEXT: call void @use(i32 [[TMP1]], i32 [[TMP2]], i32 [[TMP3]]) #[[ATTR6]] +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM: Function Attrs: norecurse nosync nounwind +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@level2a +; IS__CGSCC_OPM-SAME: (i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[ADDR:%.*]]) #[[ATTR1]] { +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @ReachableNonKernel to i32*), align 4 +; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @UnreachableNonKernel to i32*), align 4 +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[ADDR]], align 4 +; IS__CGSCC_OPM-NEXT: call void @use(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]]) #[[ATTR4]] +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM: Function Attrs: norecurse nosync nounwind +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@level2a +; IS__CGSCC_NPM-SAME: (i32 [[TMP0:%.*]]) #[[ATTR1]] { +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[ADDR_PRIV:%.*]] = alloca i32, align 4 +; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @ReachableNonKernel to i32*), align 4 +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @UnreachableNonKernel to i32*), align 4 +; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[ADDR_PRIV]], align 4 +; IS__CGSCC_NPM-NEXT: call void @use(i32 [[TMP1]], i32 [[TMP2]], i32 3) #[[ATTR4]] +; IS__CGSCC_NPM-NEXT: ret void +; +entry: + %0 = load i32, i32* addrspacecast (i32 addrspace(3)* @ReachableNonKernel to i32*), align 4 + %1 = load i32, i32* addrspacecast (i32 addrspace(3)* @UnreachableNonKernel to i32*), align 4 + %2 = load i32, i32* %addr + call void @use(i32 %0, i32 %1, i32 %2) + ret void +} + +define internal void @level2b(i32* %addr) { +; IS__TUNIT_OPM: Function Attrs: norecurse nosync nounwind +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@level2b +; IS__TUNIT_OPM-SAME: (i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[ADDR:%.*]]) #[[ATTR1]] { +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @ReachableNonKernel to i32*), align 4 +; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @UnreachableNonKernel to i32*), align 4 +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[ADDR]], align 4 +; IS__TUNIT_OPM-NEXT: call void @use(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]]) #[[ATTR6]] +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM: Function Attrs: norecurse nosync nounwind +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@level2b +; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]]) #[[ATTR1]] { +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[ADDR_PRIV:%.*]] = alloca i32, align 4 +; IS__TUNIT_NPM-NEXT: store i32 [[TMP0]], i32* [[ADDR_PRIV]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @ReachableNonKernel to i32*), align 4 +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @UnreachableNonKernel to i32*), align 4 +; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[ADDR_PRIV]], align 4 +; IS__TUNIT_NPM-NEXT: call void @use(i32 [[TMP1]], i32 [[TMP2]], i32 [[TMP3]]) #[[ATTR6]] +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM: Function Attrs: norecurse nosync nounwind +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@level2b +; IS__CGSCC_OPM-SAME: (i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[ADDR:%.*]]) #[[ATTR1]] { +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @ReachableNonKernel to i32*), align 4 +; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @UnreachableNonKernel to i32*), align 4 +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[ADDR]], align 4 +; IS__CGSCC_OPM-NEXT: call void @use(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]]) #[[ATTR4]] +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM: Function Attrs: norecurse nosync nounwind +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@level2b +; IS__CGSCC_NPM-SAME: (i32 [[TMP0:%.*]]) #[[ATTR1]] { +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[ADDR_PRIV:%.*]] = alloca i32, align 4 +; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @ReachableNonKernel to i32*), align 4 +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* addrspacecast (i32 addrspace(3)* @UnreachableNonKernel to i32*), align 4 +; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[ADDR_PRIV]], align 4 +; IS__CGSCC_NPM-NEXT: call void @use(i32 [[TMP1]], i32 [[TMP2]], i32 3) #[[ATTR4]] +; IS__CGSCC_NPM-NEXT: ret void +; +entry: + %0 = load i32, i32* addrspacecast (i32 addrspace(3)* @ReachableNonKernel to i32*), align 4 + %1 = load i32, i32* addrspacecast (i32 addrspace(3)* @UnreachableNonKernel to i32*), align 4 + %2 = load i32, i32* %addr + call void @use(i32 %0, i32 %1, i32 %2) + ret void +} + +define internal void @level2all_late(i32* %addr) { +; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly +; CHECK-LABEL: define {{[^@]+}}@level2all_late +; CHECK-SAME: (i32* noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[ADDR:%.*]]) #[[ATTR2]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: store i32 1, i32* addrspacecast (i32 addrspace(3)* @UnreachableNonKernel to i32*), align 4 +; CHECK-NEXT: store i32 5, i32* [[ADDR]], align 4 +; CHECK-NEXT: ret void +; +entry: + store i32 1, i32* addrspacecast (i32 addrspace(3)* @UnreachableNonKernel to i32*), align 4 + store i32 5, i32* %addr, align 4 + ret void +} + +declare dso_local void @use(i32, i32, i32) nosync norecurse nounwind + +;. +; IS__TUNIT____: attributes #[[ATTR0]] = { norecurse nosync nounwind "kernel" } +; IS__TUNIT____: attributes #[[ATTR1]] = { norecurse nosync nounwind } +; IS__TUNIT____: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind willreturn writeonly } +; IS__TUNIT____: attributes #[[ATTR3]] = { nofree nosync nounwind willreturn writeonly } +; IS__TUNIT____: attributes #[[ATTR4]] = { nosync nounwind } +; IS__TUNIT____: attributes #[[ATTR5]] = { nosync nounwind writeonly } +; IS__TUNIT____: attributes #[[ATTR6]] = { nounwind } +;. +; IS__CGSCC_OPM: attributes #[[ATTR0]] = { norecurse nosync nounwind "kernel" } +; IS__CGSCC_OPM: attributes #[[ATTR1]] = { norecurse nosync nounwind } +; IS__CGSCC_OPM: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind willreturn writeonly } +; IS__CGSCC_OPM: attributes #[[ATTR3]] = { nofree norecurse nosync nounwind readnone willreturn } +; IS__CGSCC_OPM: attributes #[[ATTR4]] = { nounwind } +; IS__CGSCC_OPM: attributes #[[ATTR5]] = { nounwind willreturn writeonly } +; IS__CGSCC_OPM: attributes #[[ATTR6]] = { nounwind readnone } +; IS__CGSCC_OPM: attributes #[[ATTR7]] = { nounwind writeonly } +;. +; IS__CGSCC_NPM: attributes #[[ATTR0]] = { norecurse nosync nounwind "kernel" } +; IS__CGSCC_NPM: attributes #[[ATTR1]] = { norecurse nosync nounwind } +; IS__CGSCC_NPM: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind willreturn writeonly } +; IS__CGSCC_NPM: attributes #[[ATTR3]] = { nofree norecurse nosync nounwind readnone willreturn } +; IS__CGSCC_NPM: attributes #[[ATTR4]] = { nounwind } +; IS__CGSCC_NPM: attributes #[[ATTR5]] = { nounwind willreturn writeonly } +; IS__CGSCC_NPM: attributes #[[ATTR6]] = { nounwind readnone } +; IS__CGSCC_NPM: attributes #[[ATTR7]] = { nosync nounwind } +; IS__CGSCC_NPM: attributes #[[ATTR8]] = { nosync nounwind writeonly } +;. diff --git a/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll b/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll --- a/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll +++ b/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll @@ -118,7 +118,7 @@ ; IS__TUNIT_OPM-NEXT: entry: ; IS__TUNIT_OPM-NEXT: [[S:%.*]] = alloca [[STRUCT_S]], align 4 ; IS__TUNIT_OPM-NEXT: [[I:%.*]] = bitcast %struct.S* [[S]] to i8* -; IS__TUNIT_OPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 24, i8* nocapture nofree noundef nonnull align 4 dereferenceable(24) [[I]]) #[[ATTR10:[0-9]+]] +; IS__TUNIT_OPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 24, i8* nocapture nofree noundef nonnull align 4 dereferenceable(24) [[I]]) #[[ATTR11:[0-9]+]] ; IS__TUNIT_OPM-NEXT: [[F1:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 3 ; IS__TUNIT_OPM-NEXT: [[F2:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 4 ; IS__TUNIT_OPM-NEXT: [[F3:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 5 @@ -145,7 +145,7 @@ ; IS__TUNIT_OPM-NEXT: [[I316:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[AGG_RESULT]], i64 0, i32 2 ; IS__TUNIT_OPM-NEXT: store i32 [[ADD15]], i32* [[I316]], align 4, !tbaa [[TBAA14:![0-9]+]] ; IS__TUNIT_OPM-NEXT: [[I12:%.*]] = bitcast %struct.S* [[S]] to i8* -; IS__TUNIT_OPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 24, i8* nocapture nofree noundef nonnull align 4 dereferenceable(24) [[I12]]) #[[ATTR10]] +; IS__TUNIT_OPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 24, i8* nocapture nofree noundef nonnull align 4 dereferenceable(24) [[I12]]) #[[ATTR11]] ; IS__TUNIT_OPM-NEXT: ret void ; ; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn @@ -154,7 +154,7 @@ ; IS__TUNIT_NPM-NEXT: entry: ; IS__TUNIT_NPM-NEXT: [[S:%.*]] = alloca [[STRUCT_S]], align 4 ; IS__TUNIT_NPM-NEXT: [[I:%.*]] = bitcast %struct.S* [[S]] to i8* -; IS__TUNIT_NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 24, i8* nocapture nofree noundef nonnull align 4 dereferenceable(24) [[I]]) #[[ATTR9:[0-9]+]] +; IS__TUNIT_NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 24, i8* nocapture nofree noundef nonnull align 4 dereferenceable(24) [[I]]) #[[ATTR10:[0-9]+]] ; IS__TUNIT_NPM-NEXT: [[F1:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 3 ; IS__TUNIT_NPM-NEXT: [[F2:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 4 ; IS__TUNIT_NPM-NEXT: [[F3:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 5 @@ -181,7 +181,7 @@ ; IS__TUNIT_NPM-NEXT: [[I316:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[AGG_RESULT]], i64 0, i32 2 ; IS__TUNIT_NPM-NEXT: store i32 [[ADD15]], i32* [[I316]], align 4, !tbaa [[TBAA14:![0-9]+]] ; IS__TUNIT_NPM-NEXT: [[I12:%.*]] = bitcast %struct.S* [[S]] to i8* -; IS__TUNIT_NPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 24, i8* nocapture nofree noundef nonnull align 4 dereferenceable(24) [[I12]]) #[[ATTR9]] +; IS__TUNIT_NPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 24, i8* nocapture nofree noundef nonnull align 4 dereferenceable(24) [[I12]]) #[[ATTR10]] ; IS__TUNIT_NPM-NEXT: ret void ; ; IS__CGSCC_OPM: Function Attrs: argmemonly nofree nosync nounwind willreturn @@ -190,16 +190,16 @@ ; IS__CGSCC_OPM-NEXT: entry: ; IS__CGSCC_OPM-NEXT: [[S:%.*]] = alloca [[STRUCT_S]], align 4 ; IS__CGSCC_OPM-NEXT: [[I:%.*]] = bitcast %struct.S* [[S]] to i8* -; IS__CGSCC_OPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 24, i8* nocapture nofree noundef nonnull align 4 dereferenceable(24) [[I]]) #[[ATTR13:[0-9]+]] +; IS__CGSCC_OPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 24, i8* nocapture nofree noundef nonnull align 4 dereferenceable(24) [[I]]) #[[ATTR14:[0-9]+]] ; IS__CGSCC_OPM-NEXT: [[F1:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 3 ; IS__CGSCC_OPM-NEXT: [[F2:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 4 ; IS__CGSCC_OPM-NEXT: [[F3:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 5 ; IS__CGSCC_OPM-NEXT: [[I1:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 0 -; IS__CGSCC_OPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(24) [[I1]], i32 noundef 1) #[[ATTR14:[0-9]+]] +; IS__CGSCC_OPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(24) [[I1]], i32 noundef 1) #[[ATTR15:[0-9]+]] ; IS__CGSCC_OPM-NEXT: [[I2:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 1 -; IS__CGSCC_OPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(20) [[I2]], i32 noundef 2) #[[ATTR14]] +; IS__CGSCC_OPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(20) [[I2]], i32 noundef 2) #[[ATTR15]] ; IS__CGSCC_OPM-NEXT: [[I3:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 2 -; IS__CGSCC_OPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(16) [[I3]], i32 noundef 3) #[[ATTR14]] +; IS__CGSCC_OPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(16) [[I3]], i32 noundef 3) #[[ATTR15]] ; IS__CGSCC_OPM-NEXT: [[F12:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[AGG_RESULT]], i64 0, i32 3 ; IS__CGSCC_OPM-NEXT: store float 0x3FF19999A0000000, float* [[F12]], align 4, !tbaa [[TBAA7:![0-9]+]] ; IS__CGSCC_OPM-NEXT: [[MUL:%.*]] = fmul float 0x40019999A0000000, 2.000000e+00 @@ -217,7 +217,7 @@ ; IS__CGSCC_OPM-NEXT: [[I316:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[AGG_RESULT]], i64 0, i32 2 ; IS__CGSCC_OPM-NEXT: store i32 [[ADD15]], i32* [[I316]], align 4, !tbaa [[TBAA14:![0-9]+]] ; IS__CGSCC_OPM-NEXT: [[I12:%.*]] = bitcast %struct.S* [[S]] to i8* -; IS__CGSCC_OPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 24, i8* nocapture nofree noundef nonnull align 4 dereferenceable(24) [[I12]]) #[[ATTR13]] +; IS__CGSCC_OPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 24, i8* nocapture nofree noundef nonnull align 4 dereferenceable(24) [[I12]]) #[[ATTR14]] ; IS__CGSCC_OPM-NEXT: ret void ; ; IS__CGSCC_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn @@ -226,16 +226,16 @@ ; IS__CGSCC_NPM-NEXT: entry: ; IS__CGSCC_NPM-NEXT: [[S:%.*]] = alloca [[STRUCT_S]], align 4 ; IS__CGSCC_NPM-NEXT: [[I:%.*]] = bitcast %struct.S* [[S]] to i8* -; IS__CGSCC_NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 24, i8* nocapture nofree noundef nonnull align 4 dereferenceable(24) [[I]]) #[[ATTR12:[0-9]+]] +; IS__CGSCC_NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 24, i8* nocapture nofree noundef nonnull align 4 dereferenceable(24) [[I]]) #[[ATTR13:[0-9]+]] ; IS__CGSCC_NPM-NEXT: [[F1:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 3 ; IS__CGSCC_NPM-NEXT: [[F2:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 4 ; IS__CGSCC_NPM-NEXT: [[F3:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 5 ; IS__CGSCC_NPM-NEXT: [[I1:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 0 -; IS__CGSCC_NPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(24) [[I1]], i32 noundef 1) #[[ATTR13:[0-9]+]] +; IS__CGSCC_NPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(24) [[I1]], i32 noundef 1) #[[ATTR14:[0-9]+]] ; IS__CGSCC_NPM-NEXT: [[I2:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 1 -; IS__CGSCC_NPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(20) [[I2]], i32 noundef 2) #[[ATTR13]] +; IS__CGSCC_NPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(20) [[I2]], i32 noundef 2) #[[ATTR14]] ; IS__CGSCC_NPM-NEXT: [[I3:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 2 -; IS__CGSCC_NPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(16) [[I3]], i32 noundef 3) #[[ATTR13]] +; IS__CGSCC_NPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(16) [[I3]], i32 noundef 3) #[[ATTR14]] ; IS__CGSCC_NPM-NEXT: [[F12:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[AGG_RESULT]], i64 0, i32 3 ; IS__CGSCC_NPM-NEXT: store float 0x3FF19999A0000000, float* [[F12]], align 4, !tbaa [[TBAA7:![0-9]+]] ; IS__CGSCC_NPM-NEXT: [[MUL:%.*]] = fmul float 0x40019999A0000000, 2.000000e+00 @@ -253,7 +253,7 @@ ; IS__CGSCC_NPM-NEXT: [[I316:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[AGG_RESULT]], i64 0, i32 2 ; IS__CGSCC_NPM-NEXT: store i32 [[ADD15]], i32* [[I316]], align 4, !tbaa [[TBAA14:![0-9]+]] ; IS__CGSCC_NPM-NEXT: [[I12:%.*]] = bitcast %struct.S* [[S]] to i8* -; IS__CGSCC_NPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 24, i8* nocapture nofree noundef nonnull align 4 dereferenceable(24) [[I12]]) #[[ATTR12]] +; IS__CGSCC_NPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 24, i8* nocapture nofree noundef nonnull align 4 dereferenceable(24) [[I12]]) #[[ATTR13]] ; IS__CGSCC_NPM-NEXT: ret void ; entry: @@ -414,7 +414,7 @@ ; IS__TUNIT_NPM-NEXT: entry: ; IS__TUNIT_NPM-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16 ; IS__TUNIT_NPM-NEXT: [[I:%.*]] = getelementptr inbounds [1024 x i8], [1024 x i8]* [[BYTES]], i64 0, i64 0 -; IS__TUNIT_NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 1024, i8* nocapture nofree noundef nonnull align 16 dereferenceable(1024) [[I]]) #[[ATTR9]] +; IS__TUNIT_NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 1024, i8* nocapture nofree noundef nonnull align 16 dereferenceable(1024) [[I]]) #[[ATTR10]] ; IS__TUNIT_NPM-NEXT: br label [[FOR_COND:%.*]] ; IS__TUNIT_NPM: for.cond: ; IS__TUNIT_NPM-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[ENTRY:%.*]] ] @@ -484,7 +484,7 @@ ; IS__TUNIT_NPM-NEXT: br label [[FOR_COND28]], !llvm.loop [[LOOP20:![0-9]+]] ; IS__TUNIT_NPM: for.end38: ; IS__TUNIT_NPM-NEXT: [[I24:%.*]] = getelementptr inbounds [1024 x i8], [1024 x i8]* [[BYTES]], i64 0, i64 0 -; IS__TUNIT_NPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 1024, i8* nocapture nofree noundef nonnull align 16 dereferenceable(1024) [[I24]]) #[[ATTR9]] +; IS__TUNIT_NPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 1024, i8* nocapture nofree noundef nonnull align 16 dereferenceable(1024) [[I24]]) #[[ATTR10]] ; IS__TUNIT_NPM-NEXT: ret void ; ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@local_alloca_simplifiable_2() { @@ -548,7 +548,7 @@ ; IS__CGSCC_OPM-NEXT: store i8 0, i8* [[ARRAYIDX25]], align 1, !tbaa [[TBAA15]] ; IS__CGSCC_OPM-NEXT: [[ARRAYIDX26:%.*]] = getelementptr inbounds [1024 x i8], [1024 x i8]* [[BYTES]], i64 0, i64 500 ; IS__CGSCC_OPM-NEXT: [[I22:%.*]] = bitcast i8* [[ARRAYIDX26]] to i32* -; IS__CGSCC_OPM-NEXT: call void @write_arg(i32* nofree noundef nonnull writeonly align 4 dereferenceable(4) [[I22]], i32 noundef 0) #[[ATTR15:[0-9]+]] +; IS__CGSCC_OPM-NEXT: call void @write_arg(i32* nofree noundef nonnull writeonly align 4 dereferenceable(4) [[I22]], i32 noundef 0) #[[ATTR16:[0-9]+]] ; IS__CGSCC_OPM-NEXT: br label [[FOR_COND28:%.*]] ; IS__CGSCC_OPM: for.cond28: ; IS__CGSCC_OPM-NEXT: [[INDVARS_IV12:%.*]] = phi i64 [ [[INDVARS_IV_NEXT13:%.*]], [[FOR_INC36:%.*]] ], [ 0, [[FOR_END24]] ] @@ -574,7 +574,7 @@ ; IS__CGSCC_NPM-NEXT: entry: ; IS__CGSCC_NPM-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16 ; IS__CGSCC_NPM-NEXT: [[I:%.*]] = getelementptr inbounds [1024 x i8], [1024 x i8]* [[BYTES]], i64 0, i64 0 -; IS__CGSCC_NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 1024, i8* nocapture nofree noundef nonnull align 16 dereferenceable(1024) [[I]]) #[[ATTR12]] +; IS__CGSCC_NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 1024, i8* nocapture nofree noundef nonnull align 16 dereferenceable(1024) [[I]]) #[[ATTR13]] ; IS__CGSCC_NPM-NEXT: br label [[FOR_COND:%.*]] ; IS__CGSCC_NPM: for.cond: ; IS__CGSCC_NPM-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[ENTRY:%.*]] ] @@ -631,7 +631,7 @@ ; IS__CGSCC_NPM-NEXT: store i8 0, i8* [[ARRAYIDX25]], align 1, !tbaa [[TBAA15]] ; IS__CGSCC_NPM-NEXT: [[ARRAYIDX26:%.*]] = getelementptr inbounds [1024 x i8], [1024 x i8]* [[BYTES]], i64 0, i64 500 ; IS__CGSCC_NPM-NEXT: [[I22:%.*]] = bitcast i8* [[ARRAYIDX26]] to i32* -; IS__CGSCC_NPM-NEXT: call void @write_arg(i32* nofree noundef nonnull writeonly align 4 dereferenceable(4) [[I22]], i32 noundef 0) #[[ATTR14:[0-9]+]] +; IS__CGSCC_NPM-NEXT: call void @write_arg(i32* nofree noundef nonnull writeonly align 4 dereferenceable(4) [[I22]], i32 noundef 0) #[[ATTR15:[0-9]+]] ; IS__CGSCC_NPM-NEXT: br label [[FOR_COND28:%.*]] ; IS__CGSCC_NPM: for.cond28: ; IS__CGSCC_NPM-NEXT: [[INDVARS_IV12:%.*]] = phi i64 [ [[INDVARS_IV_NEXT13:%.*]], [[FOR_INC36:%.*]] ], [ 0, [[FOR_END24]] ] @@ -842,7 +842,7 @@ ; IS__TUNIT_OPM-NEXT: entry: ; IS__TUNIT_OPM-NEXT: [[L:%.*]] = alloca i32, align 4 ; IS__TUNIT_OPM-NEXT: [[I:%.*]] = bitcast i32* [[L]] to i8* -; IS__TUNIT_OPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR10]] +; IS__TUNIT_OPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR11]] ; IS__TUNIT_OPM-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[CND]], 0 ; IS__TUNIT_OPM-NEXT: br i1 [[TOBOOL_NOT]], label [[COND_FALSE:%.*]], label [[COND_TRUE:%.*]] ; IS__TUNIT_OPM: cond.true: @@ -851,7 +851,7 @@ ; IS__TUNIT_OPM-NEXT: br label [[COND_END]] ; IS__TUNIT_OPM: cond.end: ; IS__TUNIT_OPM-NEXT: [[I2:%.*]] = bitcast i32* [[L]] to i8* -; IS__TUNIT_OPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I2]]) #[[ATTR10]] +; IS__TUNIT_OPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I2]]) #[[ATTR11]] ; IS__TUNIT_OPM-NEXT: ret i32 5 ; ; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind willreturn @@ -860,7 +860,7 @@ ; IS__TUNIT_NPM-NEXT: entry: ; IS__TUNIT_NPM-NEXT: [[L:%.*]] = alloca i32, align 4 ; IS__TUNIT_NPM-NEXT: [[I:%.*]] = bitcast i32* [[L]] to i8* -; IS__TUNIT_NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR9]] +; IS__TUNIT_NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR10]] ; IS__TUNIT_NPM-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[CND]], 0 ; IS__TUNIT_NPM-NEXT: br i1 [[TOBOOL_NOT]], label [[COND_FALSE:%.*]], label [[COND_TRUE:%.*]] ; IS__TUNIT_NPM: cond.true: @@ -869,7 +869,7 @@ ; IS__TUNIT_NPM-NEXT: br label [[COND_END]] ; IS__TUNIT_NPM: cond.end: ; IS__TUNIT_NPM-NEXT: [[I2:%.*]] = bitcast i32* [[L]] to i8* -; IS__TUNIT_NPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I2]]) #[[ATTR9]] +; IS__TUNIT_NPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I2]]) #[[ATTR10]] ; IS__TUNIT_NPM-NEXT: ret i32 5 ; ; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind willreturn @@ -878,7 +878,7 @@ ; IS__CGSCC_OPM-NEXT: entry: ; IS__CGSCC_OPM-NEXT: [[L:%.*]] = alloca i32, align 4 ; IS__CGSCC_OPM-NEXT: [[I:%.*]] = bitcast i32* [[L]] to i8* -; IS__CGSCC_OPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR13]] +; IS__CGSCC_OPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR14]] ; IS__CGSCC_OPM-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[CND]], 0 ; IS__CGSCC_OPM-NEXT: br i1 [[TOBOOL_NOT]], label [[COND_FALSE:%.*]], label [[COND_TRUE:%.*]] ; IS__CGSCC_OPM: cond.true: @@ -887,7 +887,7 @@ ; IS__CGSCC_OPM-NEXT: br label [[COND_END]] ; IS__CGSCC_OPM: cond.end: ; IS__CGSCC_OPM-NEXT: [[I2:%.*]] = bitcast i32* [[L]] to i8* -; IS__CGSCC_OPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I2]]) #[[ATTR13]] +; IS__CGSCC_OPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I2]]) #[[ATTR14]] ; IS__CGSCC_OPM-NEXT: ret i32 5 ; ; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn @@ -896,7 +896,7 @@ ; IS__CGSCC_NPM-NEXT: entry: ; IS__CGSCC_NPM-NEXT: [[L:%.*]] = alloca i32, align 4 ; IS__CGSCC_NPM-NEXT: [[I:%.*]] = bitcast i32* [[L]] to i8* -; IS__CGSCC_NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR12]] +; IS__CGSCC_NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR13]] ; IS__CGSCC_NPM-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[CND]], 0 ; IS__CGSCC_NPM-NEXT: br i1 [[TOBOOL_NOT]], label [[COND_FALSE:%.*]], label [[COND_TRUE:%.*]] ; IS__CGSCC_NPM: cond.true: @@ -905,7 +905,7 @@ ; IS__CGSCC_NPM-NEXT: br label [[COND_END]] ; IS__CGSCC_NPM: cond.end: ; IS__CGSCC_NPM-NEXT: [[I2:%.*]] = bitcast i32* [[L]] to i8* -; IS__CGSCC_NPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I2]]) #[[ATTR12]] +; IS__CGSCC_NPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I2]]) #[[ATTR13]] ; IS__CGSCC_NPM-NEXT: ret i32 5 ; entry: @@ -946,7 +946,7 @@ ; IS__TUNIT_OPM-NEXT: entry: ; IS__TUNIT_OPM-NEXT: [[L:%.*]] = alloca i32, align 4 ; IS__TUNIT_OPM-NEXT: [[I:%.*]] = bitcast i32* [[L]] to i8* -; IS__TUNIT_OPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR10]] +; IS__TUNIT_OPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR11]] ; IS__TUNIT_OPM-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[CND]], 0 ; IS__TUNIT_OPM-NEXT: br i1 [[TOBOOL_NOT]], label [[COND_FALSE:%.*]], label [[COND_TRUE:%.*]] ; IS__TUNIT_OPM: cond.true: @@ -955,7 +955,7 @@ ; IS__TUNIT_OPM-NEXT: br label [[COND_END]] ; IS__TUNIT_OPM: cond.end: ; IS__TUNIT_OPM-NEXT: [[I1:%.*]] = bitcast i32* [[L]] to i8* -; IS__TUNIT_OPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I1]]) #[[ATTR10]] +; IS__TUNIT_OPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I1]]) #[[ATTR11]] ; IS__TUNIT_OPM-NEXT: ret i32 5 ; ; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind willreturn @@ -964,7 +964,7 @@ ; IS__TUNIT_NPM-NEXT: entry: ; IS__TUNIT_NPM-NEXT: [[L:%.*]] = alloca i32, align 4 ; IS__TUNIT_NPM-NEXT: [[I:%.*]] = bitcast i32* [[L]] to i8* -; IS__TUNIT_NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR9]] +; IS__TUNIT_NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR10]] ; IS__TUNIT_NPM-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[CND]], 0 ; IS__TUNIT_NPM-NEXT: br i1 [[TOBOOL_NOT]], label [[COND_FALSE:%.*]], label [[COND_TRUE:%.*]] ; IS__TUNIT_NPM: cond.true: @@ -973,7 +973,7 @@ ; IS__TUNIT_NPM-NEXT: br label [[COND_END]] ; IS__TUNIT_NPM: cond.end: ; IS__TUNIT_NPM-NEXT: [[I1:%.*]] = bitcast i32* [[L]] to i8* -; IS__TUNIT_NPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I1]]) #[[ATTR9]] +; IS__TUNIT_NPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I1]]) #[[ATTR10]] ; IS__TUNIT_NPM-NEXT: ret i32 5 ; ; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind willreturn @@ -982,7 +982,7 @@ ; IS__CGSCC_OPM-NEXT: entry: ; IS__CGSCC_OPM-NEXT: [[L:%.*]] = alloca i32, align 4 ; IS__CGSCC_OPM-NEXT: [[I:%.*]] = bitcast i32* [[L]] to i8* -; IS__CGSCC_OPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR13]] +; IS__CGSCC_OPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR14]] ; IS__CGSCC_OPM-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[CND]], 0 ; IS__CGSCC_OPM-NEXT: br i1 [[TOBOOL_NOT]], label [[COND_FALSE:%.*]], label [[COND_TRUE:%.*]] ; IS__CGSCC_OPM: cond.true: @@ -991,7 +991,7 @@ ; IS__CGSCC_OPM-NEXT: br label [[COND_END]] ; IS__CGSCC_OPM: cond.end: ; IS__CGSCC_OPM-NEXT: [[I1:%.*]] = bitcast i32* [[L]] to i8* -; IS__CGSCC_OPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I1]]) #[[ATTR13]] +; IS__CGSCC_OPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I1]]) #[[ATTR14]] ; IS__CGSCC_OPM-NEXT: ret i32 5 ; ; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn @@ -1000,7 +1000,7 @@ ; IS__CGSCC_NPM-NEXT: entry: ; IS__CGSCC_NPM-NEXT: [[L:%.*]] = alloca i32, align 4 ; IS__CGSCC_NPM-NEXT: [[I:%.*]] = bitcast i32* [[L]] to i8* -; IS__CGSCC_NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR12]] +; IS__CGSCC_NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR13]] ; IS__CGSCC_NPM-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[CND]], 0 ; IS__CGSCC_NPM-NEXT: br i1 [[TOBOOL_NOT]], label [[COND_FALSE:%.*]], label [[COND_TRUE:%.*]] ; IS__CGSCC_NPM: cond.true: @@ -1009,7 +1009,7 @@ ; IS__CGSCC_NPM-NEXT: br label [[COND_END]] ; IS__CGSCC_NPM: cond.end: ; IS__CGSCC_NPM-NEXT: [[I1:%.*]] = bitcast i32* [[L]] to i8* -; IS__CGSCC_NPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I1]]) #[[ATTR12]] +; IS__CGSCC_NPM-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I1]]) #[[ATTR13]] ; IS__CGSCC_NPM-NEXT: ret i32 5 ; entry: @@ -1107,9 +1107,9 @@ ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@static_global_simplifiable_1 ; IS__CGSCC_OPM-SAME: (%struct.S* noalias nocapture nofree nonnull writeonly sret([[STRUCT_S:%.*]]) align 4 dereferenceable(24) [[AGG_RESULT:%.*]]) #[[ATTR4:[0-9]+]] { ; IS__CGSCC_OPM-NEXT: entry: -; IS__CGSCC_OPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(24) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i32 0, i32 0), i32 noundef 1) #[[ATTR14]] -; IS__CGSCC_OPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(20) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 1), i32 noundef 2) #[[ATTR14]] -; IS__CGSCC_OPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(16) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 2), i32 noundef 3) #[[ATTR14]] +; IS__CGSCC_OPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(24) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i32 0, i32 0), i32 noundef 1) #[[ATTR15]] +; IS__CGSCC_OPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(20) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 1), i32 noundef 2) #[[ATTR15]] +; IS__CGSCC_OPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(16) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 2), i32 noundef 3) #[[ATTR15]] ; IS__CGSCC_OPM-NEXT: [[F1:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[AGG_RESULT]], i64 0, i32 3 ; IS__CGSCC_OPM-NEXT: store float 0x3FF19999A0000000, float* [[F1]], align 4, !tbaa [[TBAA7]] ; IS__CGSCC_OPM-NEXT: [[MUL:%.*]] = fmul float 0x40019999A0000000, 2.000000e+00 @@ -1132,9 +1132,9 @@ ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@static_global_simplifiable_1 ; IS__CGSCC_NPM-SAME: (%struct.S* noalias nocapture nofree nonnull writeonly sret([[STRUCT_S:%.*]]) align 4 dereferenceable(24) [[AGG_RESULT:%.*]]) #[[ATTR4:[0-9]+]] { ; IS__CGSCC_NPM-NEXT: entry: -; IS__CGSCC_NPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(24) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i32 0, i32 0), i32 noundef 1) #[[ATTR13]] -; IS__CGSCC_NPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(20) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 1), i32 noundef 2) #[[ATTR13]] -; IS__CGSCC_NPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(16) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 2), i32 noundef 3) #[[ATTR13]] +; IS__CGSCC_NPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(24) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i32 0, i32 0), i32 noundef 1) #[[ATTR14]] +; IS__CGSCC_NPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(20) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 1), i32 noundef 2) #[[ATTR14]] +; IS__CGSCC_NPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(16) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 2), i32 noundef 3) #[[ATTR14]] ; IS__CGSCC_NPM-NEXT: [[F1:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[AGG_RESULT]], i64 0, i32 3 ; IS__CGSCC_NPM-NEXT: store float 0x3FF19999A0000000, float* [[F1]], align 4, !tbaa [[TBAA7]] ; IS__CGSCC_NPM-NEXT: [[MUL:%.*]] = fmul float 0x40019999A0000000, 2.000000e+00 @@ -1394,7 +1394,7 @@ ; IS__CGSCC_OPM-NEXT: br label [[FOR_COND13]], !llvm.loop [[LOOP26:![0-9]+]] ; IS__CGSCC_OPM: for.end23: ; IS__CGSCC_OPM-NEXT: store i8 0, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @GBytes, i64 0, i64 1023), align 1, !tbaa [[TBAA15]] -; IS__CGSCC_OPM-NEXT: call void @write_arg(i32* nofree noundef nonnull writeonly align 4 dereferenceable(4) bitcast (i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @GBytes, i64 0, i64 500) to i32*), i32 noundef 0) #[[ATTR15]] +; IS__CGSCC_OPM-NEXT: call void @write_arg(i32* nofree noundef nonnull writeonly align 4 dereferenceable(4) bitcast (i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @GBytes, i64 0, i64 500) to i32*), i32 noundef 0) #[[ATTR16]] ; IS__CGSCC_OPM-NEXT: br label [[FOR_COND25:%.*]] ; IS__CGSCC_OPM: for.cond25: ; IS__CGSCC_OPM-NEXT: [[INDVARS_IV12:%.*]] = phi i64 [ [[INDVARS_IV_NEXT13:%.*]], [[FOR_INC33:%.*]] ], [ 0, [[FOR_END23]] ] @@ -1467,7 +1467,7 @@ ; IS__CGSCC_NPM-NEXT: br label [[FOR_COND13]], !llvm.loop [[LOOP26:![0-9]+]] ; IS__CGSCC_NPM: for.end23: ; IS__CGSCC_NPM-NEXT: store i8 0, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @GBytes, i64 0, i64 1023), align 1, !tbaa [[TBAA15]] -; IS__CGSCC_NPM-NEXT: call void @write_arg(i32* nofree noundef nonnull writeonly align 4 dereferenceable(4) bitcast (i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @GBytes, i64 0, i64 500) to i32*), i32 noundef 0) #[[ATTR14]] +; IS__CGSCC_NPM-NEXT: call void @write_arg(i32* nofree noundef nonnull writeonly align 4 dereferenceable(4) bitcast (i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @GBytes, i64 0, i64 500) to i32*), i32 noundef 0) #[[ATTR15]] ; IS__CGSCC_NPM-NEXT: br label [[FOR_COND25:%.*]] ; IS__CGSCC_NPM: for.cond25: ; IS__CGSCC_NPM-NEXT: [[INDVARS_IV12:%.*]] = phi i64 [ [[INDVARS_IV_NEXT13:%.*]], [[FOR_INC33:%.*]] ], [ 0, [[FOR_END23]] ] @@ -1741,11 +1741,11 @@ ; IS__CGSCC_OPM-NEXT: [[F3:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 5 ; IS__CGSCC_OPM-NEXT: store float 0x400A666660000000, float* [[F3]], align 4, !tbaa [[TBAA11]] ; IS__CGSCC_OPM-NEXT: [[I1:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 0 -; IS__CGSCC_OPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 8 dereferenceable(24) [[I1]], i32 noundef 1) #[[ATTR14]] +; IS__CGSCC_OPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 8 dereferenceable(24) [[I1]], i32 noundef 1) #[[ATTR15]] ; IS__CGSCC_OPM-NEXT: [[I2:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 1 -; IS__CGSCC_OPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(20) [[I2]], i32 noundef 2) #[[ATTR14]] +; IS__CGSCC_OPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(20) [[I2]], i32 noundef 2) #[[ATTR15]] ; IS__CGSCC_OPM-NEXT: [[I3:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 2 -; IS__CGSCC_OPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 8 dereferenceable(16) [[I3]], i32 noundef 3) #[[ATTR14]] +; IS__CGSCC_OPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 8 dereferenceable(16) [[I3]], i32 noundef 3) #[[ATTR15]] ; IS__CGSCC_OPM-NEXT: [[F11:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 3 ; IS__CGSCC_OPM-NEXT: [[I:%.*]] = load float, float* [[F11]], align 4, !tbaa [[TBAA7]] ; IS__CGSCC_OPM-NEXT: [[F12:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[AGG_RESULT]], i64 0, i32 3 @@ -1791,11 +1791,11 @@ ; IS__CGSCC_NPM-NEXT: [[F3:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 5 ; IS__CGSCC_NPM-NEXT: store float 0x400A666660000000, float* [[F3]], align 4, !tbaa [[TBAA11]] ; IS__CGSCC_NPM-NEXT: [[I1:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 0 -; IS__CGSCC_NPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 8 dereferenceable(24) [[I1]], i32 noundef 1) #[[ATTR13]] +; IS__CGSCC_NPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 8 dereferenceable(24) [[I1]], i32 noundef 1) #[[ATTR14]] ; IS__CGSCC_NPM-NEXT: [[I2:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 1 -; IS__CGSCC_NPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(20) [[I2]], i32 noundef 2) #[[ATTR13]] +; IS__CGSCC_NPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(20) [[I2]], i32 noundef 2) #[[ATTR14]] ; IS__CGSCC_NPM-NEXT: [[I3:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 2 -; IS__CGSCC_NPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 8 dereferenceable(16) [[I3]], i32 noundef 3) #[[ATTR13]] +; IS__CGSCC_NPM-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 8 dereferenceable(16) [[I3]], i32 noundef 3) #[[ATTR14]] ; IS__CGSCC_NPM-NEXT: [[F11:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[S]], i64 0, i32 3 ; IS__CGSCC_NPM-NEXT: [[I:%.*]] = load float, float* [[F11]], align 4, !tbaa [[TBAA7]] ; IS__CGSCC_NPM-NEXT: [[F12:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[AGG_RESULT]], i64 0, i32 3 @@ -2112,7 +2112,7 @@ ; IS__CGSCC_OPM-NEXT: store i8 0, i8* [[ARRAYIDX24]], align 1, !tbaa [[TBAA15]] ; IS__CGSCC_OPM-NEXT: [[ARRAYIDX25:%.*]] = getelementptr inbounds i8, i8* [[BYTES]], i64 500 ; IS__CGSCC_OPM-NEXT: [[I21:%.*]] = bitcast i8* [[ARRAYIDX25]] to i32* -; IS__CGSCC_OPM-NEXT: call void @write_arg(i32* nofree noundef nonnull writeonly align 4 dereferenceable(4) [[I21]], i32 noundef 0) #[[ATTR15]] +; IS__CGSCC_OPM-NEXT: call void @write_arg(i32* nofree noundef nonnull writeonly align 4 dereferenceable(4) [[I21]], i32 noundef 0) #[[ATTR16]] ; IS__CGSCC_OPM-NEXT: br label [[FOR_COND27:%.*]] ; IS__CGSCC_OPM: for.cond27: ; IS__CGSCC_OPM-NEXT: [[INDVARS_IV12:%.*]] = phi i64 [ [[INDVARS_IV_NEXT13:%.*]], [[FOR_INC35:%.*]] ], [ 0, [[FOR_END23]] ] @@ -2191,7 +2191,7 @@ ; IS__CGSCC_NPM-NEXT: store i8 0, i8* [[ARRAYIDX24]], align 1, !tbaa [[TBAA15]] ; IS__CGSCC_NPM-NEXT: [[ARRAYIDX25:%.*]] = getelementptr inbounds i8, i8* [[BYTES]], i64 500 ; IS__CGSCC_NPM-NEXT: [[I21:%.*]] = bitcast i8* [[ARRAYIDX25]] to i32* -; IS__CGSCC_NPM-NEXT: call void @write_arg(i32* nofree noundef nonnull writeonly align 4 dereferenceable(4) [[I21]], i32 noundef 0) #[[ATTR14]] +; IS__CGSCC_NPM-NEXT: call void @write_arg(i32* nofree noundef nonnull writeonly align 4 dereferenceable(4) [[I21]], i32 noundef 0) #[[ATTR15]] ; IS__CGSCC_NPM-NEXT: br label [[FOR_COND27:%.*]] ; IS__CGSCC_NPM: for.cond27: ; IS__CGSCC_NPM-NEXT: [[INDVARS_IV12:%.*]] = phi i64 [ [[INDVARS_IV_NEXT13:%.*]], [[FOR_INC35:%.*]] ], [ 0, [[FOR_END23]] ] @@ -2324,9 +2324,9 @@ ; IS__TUNIT_OPM-NEXT: [[X:%.*]] = alloca i32, align 4 ; IS__TUNIT_OPM-NEXT: [[Y:%.*]] = alloca i32, align 4 ; IS__TUNIT_OPM-NEXT: [[I:%.*]] = bitcast i32* [[X]] to i8* -; IS__TUNIT_OPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR10]] +; IS__TUNIT_OPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR11]] ; IS__TUNIT_OPM-NEXT: [[I1:%.*]] = bitcast i32* [[Y]] to i8* -; IS__TUNIT_OPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I1]]) #[[ATTR10]] +; IS__TUNIT_OPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I1]]) #[[ATTR11]] ; IS__TUNIT_OPM-NEXT: store i32 1, i32* [[Y]], align 4, !tbaa [[TBAA3]] ; IS__TUNIT_OPM-NEXT: store i32 1, i32* [[X]], align 4, !tbaa [[TBAA3]] ; IS__TUNIT_OPM-NEXT: [[I2:%.*]] = bitcast i32* [[X]] to i8* @@ -2349,9 +2349,9 @@ ; IS__TUNIT_NPM-NEXT: [[X:%.*]] = alloca i32, align 4 ; IS__TUNIT_NPM-NEXT: [[Y:%.*]] = alloca i32, align 4 ; IS__TUNIT_NPM-NEXT: [[I:%.*]] = bitcast i32* [[X]] to i8* -; IS__TUNIT_NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR9]] +; IS__TUNIT_NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR10]] ; IS__TUNIT_NPM-NEXT: [[I1:%.*]] = bitcast i32* [[Y]] to i8* -; IS__TUNIT_NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I1]]) #[[ATTR9]] +; IS__TUNIT_NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I1]]) #[[ATTR10]] ; IS__TUNIT_NPM-NEXT: store i32 1, i32* [[Y]], align 4, !tbaa [[TBAA3]] ; IS__TUNIT_NPM-NEXT: store i32 1, i32* [[X]], align 4, !tbaa [[TBAA3]] ; IS__TUNIT_NPM-NEXT: [[I2:%.*]] = bitcast i32* [[X]] to i8* @@ -2374,9 +2374,9 @@ ; IS__CGSCC_OPM-NEXT: [[X:%.*]] = alloca i32, align 4 ; IS__CGSCC_OPM-NEXT: [[Y:%.*]] = alloca i32, align 4 ; IS__CGSCC_OPM-NEXT: [[I:%.*]] = bitcast i32* [[X]] to i8* -; IS__CGSCC_OPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR13]] +; IS__CGSCC_OPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR14]] ; IS__CGSCC_OPM-NEXT: [[I1:%.*]] = bitcast i32* [[Y]] to i8* -; IS__CGSCC_OPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I1]]) #[[ATTR13]] +; IS__CGSCC_OPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I1]]) #[[ATTR14]] ; IS__CGSCC_OPM-NEXT: store i32 1, i32* [[Y]], align 4, !tbaa [[TBAA3]] ; IS__CGSCC_OPM-NEXT: store i32 1, i32* [[X]], align 4, !tbaa [[TBAA3]] ; IS__CGSCC_OPM-NEXT: [[I2:%.*]] = bitcast i32* [[X]] to i8* @@ -2399,9 +2399,9 @@ ; IS__CGSCC_NPM-NEXT: [[X:%.*]] = alloca i32, align 4 ; IS__CGSCC_NPM-NEXT: [[Y:%.*]] = alloca i32, align 4 ; IS__CGSCC_NPM-NEXT: [[I:%.*]] = bitcast i32* [[X]] to i8* -; IS__CGSCC_NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR12]] +; IS__CGSCC_NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR13]] ; IS__CGSCC_NPM-NEXT: [[I1:%.*]] = bitcast i32* [[Y]] to i8* -; IS__CGSCC_NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I1]]) #[[ATTR12]] +; IS__CGSCC_NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[I1]]) #[[ATTR13]] ; IS__CGSCC_NPM-NEXT: store i32 1, i32* [[Y]], align 4, !tbaa [[TBAA3]] ; IS__CGSCC_NPM-NEXT: store i32 1, i32* [[X]], align 4, !tbaa [[TBAA3]] ; IS__CGSCC_NPM-NEXT: [[I2:%.*]] = bitcast i32* [[X]] to i8* @@ -3398,12 +3398,12 @@ ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@round_trip_malloc ; IS__TUNIT_OPM-SAME: (i32 [[X:%.*]]) { ; IS__TUNIT_OPM-NEXT: entry: -; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noalias i8* @malloc(i64 noundef 4) #[[ATTR11:[0-9]+]] +; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noalias i8* @malloc(i64 noundef 4) #[[ATTR12:[0-9]+]] ; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = bitcast i8* [[CALL]] to i32* ; IS__TUNIT_OPM-NEXT: store i32 [[X]], i32* [[TMP0]], align 4 ; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4 ; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = bitcast i32* [[TMP0]] to i8* -; IS__TUNIT_OPM-NEXT: call void @free(i8* noundef [[TMP2]]) #[[ATTR11]] +; IS__TUNIT_OPM-NEXT: call void @free(i8* noundef [[TMP2]]) #[[ATTR12]] ; IS__TUNIT_OPM-NEXT: ret i32 [[TMP1]] ; ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@round_trip_malloc @@ -3449,12 +3449,12 @@ define dso_local i32 @round_trip_malloc_constant() { ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@round_trip_malloc_constant() { ; IS__TUNIT_OPM-NEXT: entry: -; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noalias i8* @malloc(i64 noundef 4) #[[ATTR11]] +; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noalias i8* @malloc(i64 noundef 4) #[[ATTR12]] ; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = bitcast i8* [[CALL]] to i32* ; IS__TUNIT_OPM-NEXT: store i32 7, i32* [[TMP0]], align 4 ; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4 ; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = bitcast i32* [[TMP0]] to i8* -; IS__TUNIT_OPM-NEXT: call void @free(i8* noundef [[TMP2]]) #[[ATTR11]] +; IS__TUNIT_OPM-NEXT: call void @free(i8* noundef [[TMP2]]) #[[ATTR12]] ; IS__TUNIT_OPM-NEXT: ret i32 [[TMP1]] ; ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@round_trip_malloc_constant() { @@ -3497,7 +3497,7 @@ ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@conditional_malloc ; IS__TUNIT_OPM-SAME: (i32 [[X:%.*]]) { ; IS__TUNIT_OPM-NEXT: entry: -; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noalias i8* @malloc(i64 noundef 4) #[[ATTR11]] +; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noalias i8* @malloc(i64 noundef 4) #[[ATTR12]] ; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = bitcast i8* [[CALL]] to i32* ; IS__TUNIT_OPM-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[X]], 0 ; IS__TUNIT_OPM-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] @@ -3570,7 +3570,7 @@ ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@round_trip_calloc ; IS__TUNIT_OPM-SAME: (i32 [[X:%.*]]) { ; IS__TUNIT_OPM-NEXT: entry: -; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noalias i8* @calloc(i64 noundef 4, i64 noundef 1) #[[ATTR11]] +; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noalias i8* @calloc(i64 noundef 4, i64 noundef 1) #[[ATTR12]] ; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = bitcast i8* [[CALL]] to i32* ; IS__TUNIT_OPM-NEXT: store i32 [[X]], i32* [[TMP0]], align 4 ; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4 @@ -3620,7 +3620,7 @@ define dso_local i32 @round_trip_calloc_constant() { ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@round_trip_calloc_constant() { ; IS__TUNIT_OPM-NEXT: entry: -; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noalias i8* @calloc(i64 noundef 4, i64 noundef 1) #[[ATTR11]] +; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noalias i8* @calloc(i64 noundef 4, i64 noundef 1) #[[ATTR12]] ; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = bitcast i8* [[CALL]] to i32* ; IS__TUNIT_OPM-NEXT: store i32 11, i32* [[TMP0]], align 4 ; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4 @@ -3672,7 +3672,7 @@ ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@conditional_calloc ; IS__TUNIT_OPM-SAME: (i32 [[X:%.*]]) { ; IS__TUNIT_OPM-NEXT: entry: -; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noalias i8* @calloc(i64 noundef 1, i64 noundef 4) #[[ATTR11]] +; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noalias i8* @calloc(i64 noundef 1, i64 noundef 4) #[[ATTR12]] ; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = bitcast i8* [[CALL]] to i32* ; IS__TUNIT_OPM-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[X]], 0 ; IS__TUNIT_OPM-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] @@ -3682,7 +3682,7 @@ ; IS__TUNIT_OPM: if.end: ; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4 ; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = bitcast i32* [[TMP0]] to i8* -; IS__TUNIT_OPM-NEXT: call void @free(i8* [[TMP2]]) #[[ATTR11]] +; IS__TUNIT_OPM-NEXT: call void @free(i8* [[TMP2]]) #[[ATTR12]] ; IS__TUNIT_OPM-NEXT: ret i32 [[TMP1]] ; ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@conditional_calloc @@ -3756,7 +3756,7 @@ ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@conditional_calloc_zero ; IS__TUNIT_OPM-SAME: (i1 [[C:%.*]]) { ; IS__TUNIT_OPM-NEXT: entry: -; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noalias i8* @calloc(i64 noundef 1, i64 noundef 4) #[[ATTR11]] +; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noalias i8* @calloc(i64 noundef 1, i64 noundef 4) #[[ATTR12]] ; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = bitcast i8* [[CALL]] to i32* ; IS__TUNIT_OPM-NEXT: br i1 [[C]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] ; IS__TUNIT_OPM: if.then: @@ -3765,7 +3765,7 @@ ; IS__TUNIT_OPM: if.end: ; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4 ; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = bitcast i32* [[TMP0]] to i8* -; IS__TUNIT_OPM-NEXT: call void @free(i8* [[TMP2]]) #[[ATTR11]] +; IS__TUNIT_OPM-NEXT: call void @free(i8* [[TMP2]]) #[[ATTR12]] ; IS__TUNIT_OPM-NEXT: ret i32 [[TMP1]] ; ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@conditional_calloc_zero @@ -3830,7 +3830,7 @@ ; IS__TUNIT_OPM-SAME: (i32 [[S:%.*]]) { ; IS__TUNIT_OPM-NEXT: entry: ; IS__TUNIT_OPM-NEXT: [[CONV:%.*]] = sext i32 [[S]] to i64 -; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noalias i8* @malloc(i64 [[CONV]]) #[[ATTR11]] +; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noalias i8* @malloc(i64 [[CONV]]) #[[ATTR12]] ; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = bitcast i8* [[CALL]] to i32* ; IS__TUNIT_OPM-NEXT: ret i32* [[TMP0]] ; @@ -3838,7 +3838,7 @@ ; IS__TUNIT_NPM-SAME: (i32 [[S:%.*]]) { ; IS__TUNIT_NPM-NEXT: entry: ; IS__TUNIT_NPM-NEXT: [[CONV:%.*]] = sext i32 [[S]] to i64 -; IS__TUNIT_NPM-NEXT: [[CALL:%.*]] = call noalias i8* @malloc(i64 [[CONV]]) #[[ATTR10:[0-9]+]] +; IS__TUNIT_NPM-NEXT: [[CALL:%.*]] = call noalias i8* @malloc(i64 [[CONV]]) #[[ATTR11:[0-9]+]] ; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = bitcast i8* [[CALL]] to i32* ; IS__TUNIT_NPM-NEXT: ret i32* [[TMP0]] ; @@ -3871,21 +3871,21 @@ ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@round_trip_malloc_like ; IS__TUNIT_OPM-SAME: (i32 [[X:%.*]]) { ; IS__TUNIT_OPM-NEXT: entry: -; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call i32* @malloc_like(i32 noundef 4) #[[ATTR11]] +; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call i32* @malloc_like(i32 noundef 4) #[[ATTR12]] ; IS__TUNIT_OPM-NEXT: store i32 [[X]], i32* [[CALL]], align 4 ; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[CALL]], align 4 ; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = bitcast i32* [[CALL]] to i8* -; IS__TUNIT_OPM-NEXT: call void @free(i8* noundef [[TMP1]]) #[[ATTR11]] +; IS__TUNIT_OPM-NEXT: call void @free(i8* noundef [[TMP1]]) #[[ATTR12]] ; IS__TUNIT_OPM-NEXT: ret i32 [[TMP0]] ; ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@round_trip_malloc_like ; IS__TUNIT_NPM-SAME: (i32 [[X:%.*]]) { ; IS__TUNIT_NPM-NEXT: entry: -; IS__TUNIT_NPM-NEXT: [[CALL:%.*]] = call i32* @malloc_like(i32 noundef 4) #[[ATTR10]] +; IS__TUNIT_NPM-NEXT: [[CALL:%.*]] = call i32* @malloc_like(i32 noundef 4) #[[ATTR11]] ; IS__TUNIT_NPM-NEXT: store i32 [[X]], i32* [[CALL]], align 4 ; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[CALL]], align 4 ; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = bitcast i32* [[CALL]] to i8* -; IS__TUNIT_NPM-NEXT: call void @free(i8* noundef [[TMP1]]) #[[ATTR10]] +; IS__TUNIT_NPM-NEXT: call void @free(i8* noundef [[TMP1]]) #[[ATTR11]] ; IS__TUNIT_NPM-NEXT: ret i32 [[TMP0]] ; ; IS__CGSCC_OPM: Function Attrs: norecurse @@ -3923,21 +3923,21 @@ ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@round_trip_unknown_alloc ; IS__TUNIT_OPM-SAME: (i32 [[X:%.*]]) { ; IS__TUNIT_OPM-NEXT: entry: -; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call i32* @unknown_alloc(i32 noundef 4) #[[ATTR11]] +; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call i32* @unknown_alloc(i32 noundef 4) #[[ATTR12]] ; IS__TUNIT_OPM-NEXT: store i32 [[X]], i32* [[CALL]], align 4 ; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[CALL]], align 4 ; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = bitcast i32* [[CALL]] to i8* -; IS__TUNIT_OPM-NEXT: call void @free(i8* noundef [[TMP1]]) #[[ATTR11]] +; IS__TUNIT_OPM-NEXT: call void @free(i8* noundef [[TMP1]]) #[[ATTR12]] ; IS__TUNIT_OPM-NEXT: ret i32 [[TMP0]] ; ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@round_trip_unknown_alloc ; IS__TUNIT_NPM-SAME: (i32 [[X:%.*]]) { ; IS__TUNIT_NPM-NEXT: entry: -; IS__TUNIT_NPM-NEXT: [[CALL:%.*]] = call i32* @unknown_alloc(i32 noundef 4) #[[ATTR10]] +; IS__TUNIT_NPM-NEXT: [[CALL:%.*]] = call i32* @unknown_alloc(i32 noundef 4) #[[ATTR11]] ; IS__TUNIT_NPM-NEXT: store i32 [[X]], i32* [[CALL]], align 4 ; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[CALL]], align 4 ; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = bitcast i32* [[CALL]] to i8* -; IS__TUNIT_NPM-NEXT: call void @free(i8* noundef [[TMP1]]) #[[ATTR10]] +; IS__TUNIT_NPM-NEXT: call void @free(i8* noundef [[TMP1]]) #[[ATTR11]] ; IS__TUNIT_NPM-NEXT: ret i32 [[TMP0]] ; ; IS__CGSCC_OPM: Function Attrs: norecurse @@ -3977,7 +3977,7 @@ ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@conditional_unknown_alloc ; IS__TUNIT_OPM-SAME: (i32 [[X:%.*]]) { ; IS__TUNIT_OPM-NEXT: entry: -; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noalias i32* @unknown_alloc(i32 noundef 4) #[[ATTR11]] +; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noalias i32* @unknown_alloc(i32 noundef 4) #[[ATTR12]] ; IS__TUNIT_OPM-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[X]], 0 ; IS__TUNIT_OPM-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] ; IS__TUNIT_OPM: if.then: @@ -3986,13 +3986,13 @@ ; IS__TUNIT_OPM: if.end: ; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[CALL]], align 4 ; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = bitcast i32* [[CALL]] to i8* -; IS__TUNIT_OPM-NEXT: call void @free(i8* [[TMP1]]) #[[ATTR11]] +; IS__TUNIT_OPM-NEXT: call void @free(i8* [[TMP1]]) #[[ATTR12]] ; IS__TUNIT_OPM-NEXT: ret i32 [[TMP0]] ; ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@conditional_unknown_alloc ; IS__TUNIT_NPM-SAME: (i32 [[X:%.*]]) { ; IS__TUNIT_NPM-NEXT: entry: -; IS__TUNIT_NPM-NEXT: [[CALL:%.*]] = call noalias i32* @unknown_alloc(i32 noundef 4) #[[ATTR10]] +; IS__TUNIT_NPM-NEXT: [[CALL:%.*]] = call noalias i32* @unknown_alloc(i32 noundef 4) #[[ATTR11]] ; IS__TUNIT_NPM-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[X]], 0 ; IS__TUNIT_NPM-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] ; IS__TUNIT_NPM: if.then: @@ -4001,7 +4001,7 @@ ; IS__TUNIT_NPM: if.end: ; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[CALL]], align 4 ; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = bitcast i32* [[CALL]] to i8* -; IS__TUNIT_NPM-NEXT: call void @free(i8* [[TMP1]]) #[[ATTR10]] +; IS__TUNIT_NPM-NEXT: call void @free(i8* [[TMP1]]) #[[ATTR11]] ; IS__TUNIT_NPM-NEXT: ret i32 [[TMP0]] ; ; IS__CGSCC_OPM: Function Attrs: norecurse @@ -4071,7 +4071,7 @@ ; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = bitcast i8* [[SRC2]] to double** ; IS__TUNIT_OPM-NEXT: store double* [[SRC]], double** [[TMP0]], align 8 ; IS__TUNIT_OPM-NEXT: store i8* [[CALL]], i8** bitcast (%struct.STy** getelementptr inbounds ([[STRUCT_STY]], %struct.STy* @global, i64 0, i32 2) to i8**), align 8 -; IS__TUNIT_OPM-NEXT: call fastcc void @nested_memory_callee(%struct.STy* noalias nocapture nofree noundef nonnull readonly align 8 dereferenceable(24) [[LOCAL]]) #[[ATTR12:[0-9]+]] +; IS__TUNIT_OPM-NEXT: call fastcc void @nested_memory_callee(%struct.STy* noalias nocapture nofree noundef nonnull readonly align 8 dereferenceable(24) [[LOCAL]]) #[[ATTR13:[0-9]+]] ; IS__TUNIT_OPM-NEXT: ret void ; ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@test_nested_memory @@ -4093,7 +4093,7 @@ ; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = load double*, double** [[LOCAL_0_1]], align 8 ; IS__TUNIT_NPM-NEXT: [[LOCAL_0_2:%.*]] = getelementptr [[STRUCT_STY]], %struct.STy* [[LOCAL]], i32 0, i32 2 ; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = load %struct.STy*, %struct.STy** [[LOCAL_0_2]], align 8 -; IS__TUNIT_NPM-NEXT: call fastcc void @nested_memory_callee(float* [[TMP2]], double* [[TMP3]], %struct.STy* [[TMP4]]) #[[ATTR11:[0-9]+]] +; IS__TUNIT_NPM-NEXT: call fastcc void @nested_memory_callee(float* [[TMP2]], double* [[TMP3]], %struct.STy* [[TMP4]]) #[[ATTR12:[0-9]+]] ; IS__TUNIT_NPM-NEXT: ret void ; ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test_nested_memory @@ -4110,7 +4110,7 @@ ; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = bitcast i8* [[SRC2]] to double** ; IS__CGSCC_OPM-NEXT: store double* [[SRC]], double** [[TMP1]], align 8 ; IS__CGSCC_OPM-NEXT: store i8* [[CALL]], i8** bitcast (%struct.STy** getelementptr inbounds ([[STRUCT_STY]], %struct.STy* @global, i64 0, i32 2) to i8**), align 8 -; IS__CGSCC_OPM-NEXT: call fastcc void @nested_memory_callee(%struct.STy* noalias nocapture nofree noundef nonnull readonly align 8 dereferenceable(24) [[LOCAL]]) #[[ATTR15]] +; IS__CGSCC_OPM-NEXT: call fastcc void @nested_memory_callee(%struct.STy* noalias nocapture nofree noundef nonnull readonly align 8 dereferenceable(24) [[LOCAL]]) #[[ATTR16]] ; IS__CGSCC_OPM-NEXT: ret void ; ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test_nested_memory @@ -4126,7 +4126,7 @@ ; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = bitcast i8* [[SRC2]] to double** ; IS__CGSCC_NPM-NEXT: store double* [[SRC]], double** [[TMP2]], align 8 ; IS__CGSCC_NPM-NEXT: store i8* [[TMP1]], i8** bitcast (%struct.STy** getelementptr inbounds ([[STRUCT_STY]], %struct.STy* @global, i64 0, i32 2) to i8**), align 8 -; IS__CGSCC_NPM-NEXT: call fastcc void @nested_memory_callee(float* noalias nocapture nofree nonnull readnone undef, double* noalias nocapture nofree nonnull readnone undef, %struct.STy* noalias nocapture nofree nonnull readnone align 8 dereferenceable(24) undef) #[[ATTR14]] +; IS__CGSCC_NPM-NEXT: call fastcc void @nested_memory_callee(float* noalias nocapture nofree nonnull readnone undef, double* noalias nocapture nofree nonnull readnone undef, %struct.STy* noalias nocapture nofree nonnull readnone align 8 dereferenceable(24) undef) #[[ATTR15]] ; IS__CGSCC_NPM-NEXT: ret void ; entry: @@ -4264,6 +4264,241 @@ ret void } +define dso_local void @entry(i32 %C) norecurse { +; IS__TUNIT_OPM: Function Attrs: norecurse nosync nounwind +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@entry +; IS__TUNIT_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR10:[0-9]+]] { +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: call void @level1(i32 [[C]]) #[[ATTR14:[0-9]+]] +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM: Function Attrs: norecurse nosync nounwind +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@entry +; IS__TUNIT_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR8:[0-9]+]] { +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: call void @level1(i32 [[C]]) #[[ATTR13:[0-9]+]] +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM: Function Attrs: norecurse nosync nounwind +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@entry +; IS__CGSCC_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR13:[0-9]+]] { +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: call void @level1(i32 [[C]]) #[[ATTR16]] +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM: Function Attrs: norecurse nosync nounwind +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@entry +; IS__CGSCC_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR11:[0-9]+]] { +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: call void @level1(i32 [[C]]) #[[ATTR15]] +; IS__CGSCC_NPM-NEXT: ret void +; +entry: + call void @level1(i32 %C) + ret void +} + +define internal void @level1(i32 %C) { +; IS__TUNIT_OPM: Function Attrs: norecurse nosync nounwind +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@level1 +; IS__TUNIT_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR10]] { +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[REACHABLE:%.*]] = alloca i32, align 4 +; IS__TUNIT_OPM-NEXT: [[UNREACHABLE:%.*]] = alloca i32, align 4 +; IS__TUNIT_OPM-NEXT: store i32 1, i32* [[REACHABLE]], align 4 +; IS__TUNIT_OPM-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[C]], 0 +; IS__TUNIT_OPM-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; IS__TUNIT_OPM: if.then: +; IS__TUNIT_OPM-NEXT: call void @level2a(i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[REACHABLE]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[UNREACHABLE]]) #[[ATTR14]] +; IS__TUNIT_OPM-NEXT: br label [[IF_END:%.*]] +; IS__TUNIT_OPM: if.else: +; IS__TUNIT_OPM-NEXT: call void @level2b(i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[REACHABLE]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[UNREACHABLE]]) #[[ATTR14]] +; IS__TUNIT_OPM-NEXT: br label [[IF_END]] +; IS__TUNIT_OPM: if.end: +; IS__TUNIT_OPM-NEXT: store i32 1, i32* [[UNREACHABLE]], align 4 +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM: Function Attrs: norecurse nosync nounwind +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@level1 +; IS__TUNIT_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR8]] { +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[REACHABLE:%.*]] = alloca i32, align 4 +; IS__TUNIT_NPM-NEXT: [[UNREACHABLE:%.*]] = alloca i32, align 4 +; IS__TUNIT_NPM-NEXT: store i32 1, i32* [[REACHABLE]], align 4 +; IS__TUNIT_NPM-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[C]], 0 +; IS__TUNIT_NPM-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; IS__TUNIT_NPM: if.then: +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[REACHABLE]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[UNREACHABLE]], align 4 +; IS__TUNIT_NPM-NEXT: call void @level2a(i32 [[TMP0]], i32 [[TMP1]]) #[[ATTR13]] +; IS__TUNIT_NPM-NEXT: br label [[IF_END:%.*]] +; IS__TUNIT_NPM: if.else: +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[REACHABLE]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[UNREACHABLE]], align 4 +; IS__TUNIT_NPM-NEXT: call void @level2b(i32 [[TMP2]], i32 [[TMP3]]) #[[ATTR13]] +; IS__TUNIT_NPM-NEXT: br label [[IF_END]] +; IS__TUNIT_NPM: if.end: +; IS__TUNIT_NPM-NEXT: store i32 1, i32* [[UNREACHABLE]], align 4 +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM: Function Attrs: norecurse nosync nounwind +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@level1 +; IS__CGSCC_OPM-SAME: (i32 [[C:%.*]]) #[[ATTR13]] { +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: [[REACHABLE:%.*]] = alloca i32, align 4 +; IS__CGSCC_OPM-NEXT: [[UNREACHABLE:%.*]] = alloca i32, align 4 +; IS__CGSCC_OPM-NEXT: store i32 1, i32* [[REACHABLE]], align 4 +; IS__CGSCC_OPM-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[C]], 0 +; IS__CGSCC_OPM-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; IS__CGSCC_OPM: if.then: +; IS__CGSCC_OPM-NEXT: call void @level2a(i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[REACHABLE]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[UNREACHABLE]]) #[[ATTR16]] +; IS__CGSCC_OPM-NEXT: br label [[IF_END:%.*]] +; IS__CGSCC_OPM: if.else: +; IS__CGSCC_OPM-NEXT: call void @level2b(i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[REACHABLE]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[UNREACHABLE]]) #[[ATTR16]] +; IS__CGSCC_OPM-NEXT: br label [[IF_END]] +; IS__CGSCC_OPM: if.end: +; IS__CGSCC_OPM-NEXT: store i32 1, i32* [[UNREACHABLE]], align 4 +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM: Function Attrs: norecurse nosync nounwind +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@level1 +; IS__CGSCC_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR11]] { +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[REACHABLE:%.*]] = alloca i32, align 4 +; IS__CGSCC_NPM-NEXT: [[UNREACHABLE:%.*]] = alloca i32, align 4 +; IS__CGSCC_NPM-NEXT: store i32 1, i32* [[REACHABLE]], align 4 +; IS__CGSCC_NPM-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[C]], 0 +; IS__CGSCC_NPM-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; IS__CGSCC_NPM: if.then: +; IS__CGSCC_NPM-NEXT: call void @level2a(i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[REACHABLE]], i32 undef) #[[ATTR15]] +; IS__CGSCC_NPM-NEXT: br label [[IF_END:%.*]] +; IS__CGSCC_NPM: if.else: +; IS__CGSCC_NPM-NEXT: call void @level2b(i32 undef, i32 undef) #[[ATTR16:[0-9]+]] +; IS__CGSCC_NPM-NEXT: br label [[IF_END]] +; IS__CGSCC_NPM: if.end: +; IS__CGSCC_NPM-NEXT: store i32 1, i32* [[UNREACHABLE]], align 4 +; IS__CGSCC_NPM-NEXT: ret void +; +entry: + %Reachable = alloca i32 + %Unreachable = alloca i32 + store i32 1, i32* %Reachable, align 4 + %tobool = icmp ne i32 %C, 0 + br i1 %tobool, label %if.then, label %if.else + +if.then: ; preds = %entry + call void @level2a(i32* %Reachable, i32* %Unreachable) + br label %if.end + +if.else: ; preds = %entry + call void @level2b(i32* %Reachable, i32* %Unreachable) + br label %if.end + +if.end: ; preds = %if.else, %if.then + store i32 1, i32* %Unreachable, align 4 + ret void +} + +define internal void @level2a(i32* %Reachable, i32* %Unreachable) { +; IS__TUNIT_OPM: Function Attrs: norecurse nosync nounwind +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@level2a +; IS__TUNIT_OPM-SAME: (i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[REACHABLE:%.*]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[UNREACHABLE:%.*]]) #[[ATTR10]] { +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[REACHABLE]], align 4 +; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[UNREACHABLE]], align 4 +; IS__TUNIT_OPM-NEXT: call void @use(i32 [[TMP0]], i32 [[TMP1]]) #[[ATTR13]] +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM: Function Attrs: norecurse nosync nounwind +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@level2a +; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR8]] { +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[UNREACHABLE_PRIV:%.*]] = alloca i32, align 4 +; IS__TUNIT_NPM-NEXT: store i32 [[TMP1]], i32* [[UNREACHABLE_PRIV]], align 4 +; IS__TUNIT_NPM-NEXT: [[REACHABLE_PRIV:%.*]] = alloca i32, align 4 +; IS__TUNIT_NPM-NEXT: store i32 [[TMP0]], i32* [[REACHABLE_PRIV]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[REACHABLE_PRIV]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[UNREACHABLE_PRIV]], align 4 +; IS__TUNIT_NPM-NEXT: call void @use(i32 [[TMP2]], i32 [[TMP3]]) #[[ATTR12]] +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM: Function Attrs: norecurse nosync nounwind +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@level2a +; IS__CGSCC_OPM-SAME: (i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[REACHABLE:%.*]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[UNREACHABLE:%.*]]) #[[ATTR13]] { +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[REACHABLE]], align 4 +; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[UNREACHABLE]], align 4 +; IS__CGSCC_OPM-NEXT: call void @use(i32 [[TMP0]], i32 [[TMP1]]) #[[ATTR16]] +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM: Function Attrs: norecurse nosync nounwind +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@level2a +; IS__CGSCC_NPM-SAME: (i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[REACHABLE:%.*]], i32 [[TMP0:%.*]]) #[[ATTR11]] { +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[UNREACHABLE_PRIV:%.*]] = alloca i32, align 4 +; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[REACHABLE]], align 4 +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[UNREACHABLE_PRIV]], align 4 +; IS__CGSCC_NPM-NEXT: call void @use(i32 [[TMP1]], i32 undef) #[[ATTR15]] +; IS__CGSCC_NPM-NEXT: ret void +; +entry: + %0 = load i32, i32* %Reachable, align 4 + %1 = load i32, i32* %Unreachable, align 4 + call void @use(i32 %0, i32 %1) + ret void +} + +define internal void @level2b(i32* %Reachable, i32* %Unreachable) { +; IS__TUNIT_OPM: Function Attrs: norecurse nosync nounwind +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@level2b +; IS__TUNIT_OPM-SAME: (i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[REACHABLE:%.*]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[UNREACHABLE:%.*]]) #[[ATTR10]] { +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[REACHABLE]], align 4 +; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[UNREACHABLE]], align 4 +; IS__TUNIT_OPM-NEXT: call void @use(i32 [[TMP0]], i32 [[TMP1]]) #[[ATTR13]] +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM: Function Attrs: norecurse nosync nounwind +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@level2b +; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR8]] { +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[UNREACHABLE_PRIV:%.*]] = alloca i32, align 4 +; IS__TUNIT_NPM-NEXT: store i32 [[TMP1]], i32* [[UNREACHABLE_PRIV]], align 4 +; IS__TUNIT_NPM-NEXT: [[REACHABLE_PRIV:%.*]] = alloca i32, align 4 +; IS__TUNIT_NPM-NEXT: store i32 [[TMP0]], i32* [[REACHABLE_PRIV]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[REACHABLE_PRIV]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[UNREACHABLE_PRIV]], align 4 +; IS__TUNIT_NPM-NEXT: call void @use(i32 [[TMP2]], i32 [[TMP3]]) #[[ATTR12]] +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM: Function Attrs: norecurse nosync nounwind +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@level2b +; IS__CGSCC_OPM-SAME: (i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[REACHABLE:%.*]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[UNREACHABLE:%.*]]) #[[ATTR13]] { +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[REACHABLE]], align 4 +; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[UNREACHABLE]], align 4 +; IS__CGSCC_OPM-NEXT: call void @use(i32 [[TMP0]], i32 [[TMP1]]) #[[ATTR16]] +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM: Function Attrs: norecurse nosync nounwind +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@level2b +; IS__CGSCC_NPM-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR11]] { +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[UNREACHABLE_PRIV:%.*]] = alloca i32, align 4 +; IS__CGSCC_NPM-NEXT: [[REACHABLE_PRIV:%.*]] = alloca i32, align 4 +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[REACHABLE_PRIV]], align 4 +; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[UNREACHABLE_PRIV]], align 4 +; IS__CGSCC_NPM-NEXT: call void @use(i32 1, i32 undef) #[[ATTR15]] +; IS__CGSCC_NPM-NEXT: ret void +; +entry: + %0 = load i32, i32* %Reachable, align 4 + %1 = load i32, i32* %Unreachable, align 4 + call void @use(i32 %0, i32 %1) + ret void +} + +declare dso_local void @use(i32, i32) nosync norecurse nounwind !llvm.module.flags = !{!0, !1} !llvm.ident = !{!2} @@ -4311,9 +4546,11 @@ ; IS__TUNIT_OPM: attributes #[[ATTR7]] = { nofree nosync nounwind readonly willreturn } ; IS__TUNIT_OPM: attributes #[[ATTR8]] = { nofree nosync nounwind readnone } ; IS__TUNIT_OPM: attributes #[[ATTR9]] = { nofree norecurse nosync nounwind uwtable willreturn } -; IS__TUNIT_OPM: attributes #[[ATTR10]] = { willreturn } -; IS__TUNIT_OPM: attributes #[[ATTR11]] = { norecurse } -; IS__TUNIT_OPM: attributes #[[ATTR12]] = { nounwind } +; IS__TUNIT_OPM: attributes #[[ATTR10]] = { norecurse nosync nounwind } +; IS__TUNIT_OPM: attributes #[[ATTR11]] = { willreturn } +; IS__TUNIT_OPM: attributes #[[ATTR12]] = { norecurse } +; IS__TUNIT_OPM: attributes #[[ATTR13]] = { nounwind } +; IS__TUNIT_OPM: attributes #[[ATTR14]] = { nosync nounwind } ;. ; IS__TUNIT_NPM: attributes #[[ATTR0]] = { argmemonly nofree nosync nounwind willreturn writeonly } ; IS__TUNIT_NPM: attributes #[[ATTR1]] = { argmemonly nofree nosync nounwind willreturn } @@ -4323,10 +4560,12 @@ ; IS__TUNIT_NPM: attributes #[[ATTR5]] = { nofree nosync nounwind readonly willreturn } ; IS__TUNIT_NPM: attributes #[[ATTR6]] = { nofree nosync nounwind writeonly } ; IS__TUNIT_NPM: attributes #[[ATTR7]] = { nofree norecurse nosync nounwind uwtable willreturn } -; IS__TUNIT_NPM: attributes #[[ATTR8:[0-9]+]] = { argmemonly nofree nounwind willreturn writeonly } -; IS__TUNIT_NPM: attributes #[[ATTR9]] = { willreturn } -; IS__TUNIT_NPM: attributes #[[ATTR10]] = { norecurse } -; IS__TUNIT_NPM: attributes #[[ATTR11]] = { nounwind } +; IS__TUNIT_NPM: attributes #[[ATTR8]] = { norecurse nosync nounwind } +; IS__TUNIT_NPM: attributes #[[ATTR9:[0-9]+]] = { argmemonly nofree nounwind willreturn writeonly } +; IS__TUNIT_NPM: attributes #[[ATTR10]] = { willreturn } +; IS__TUNIT_NPM: attributes #[[ATTR11]] = { norecurse } +; IS__TUNIT_NPM: attributes #[[ATTR12]] = { nounwind } +; IS__TUNIT_NPM: attributes #[[ATTR13]] = { nosync nounwind } ;. ; IS__CGSCC_OPM: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly } ; IS__CGSCC_OPM: attributes #[[ATTR1]] = { argmemonly nofree nosync nounwind willreturn } @@ -4341,9 +4580,10 @@ ; IS__CGSCC_OPM: attributes #[[ATTR10]] = { nofree norecurse nosync nounwind writeonly } ; IS__CGSCC_OPM: attributes #[[ATTR11]] = { norecurse } ; IS__CGSCC_OPM: attributes #[[ATTR12]] = { nofree norecurse nosync nounwind uwtable willreturn } -; IS__CGSCC_OPM: attributes #[[ATTR13]] = { willreturn } -; IS__CGSCC_OPM: attributes #[[ATTR14]] = { nounwind willreturn writeonly } -; IS__CGSCC_OPM: attributes #[[ATTR15]] = { nounwind } +; IS__CGSCC_OPM: attributes #[[ATTR13]] = { norecurse nosync nounwind } +; IS__CGSCC_OPM: attributes #[[ATTR14]] = { willreturn } +; IS__CGSCC_OPM: attributes #[[ATTR15]] = { nounwind willreturn writeonly } +; IS__CGSCC_OPM: attributes #[[ATTR16]] = { nounwind } ;. ; IS__CGSCC_NPM: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly } ; IS__CGSCC_NPM: attributes #[[ATTR1]] = { argmemonly nofree nosync nounwind willreturn } @@ -4356,10 +4596,12 @@ ; IS__CGSCC_NPM: attributes #[[ATTR8]] = { nofree norecurse nosync nounwind writeonly } ; IS__CGSCC_NPM: attributes #[[ATTR9]] = { norecurse } ; IS__CGSCC_NPM: attributes #[[ATTR10]] = { nofree norecurse nosync nounwind uwtable willreturn } -; IS__CGSCC_NPM: attributes #[[ATTR11:[0-9]+]] = { argmemonly nofree nounwind willreturn writeonly } -; IS__CGSCC_NPM: attributes #[[ATTR12]] = { willreturn } -; IS__CGSCC_NPM: attributes #[[ATTR13]] = { nounwind willreturn writeonly } -; IS__CGSCC_NPM: attributes #[[ATTR14]] = { nounwind } +; IS__CGSCC_NPM: attributes #[[ATTR11]] = { norecurse nosync nounwind } +; IS__CGSCC_NPM: attributes #[[ATTR12:[0-9]+]] = { argmemonly nofree nounwind willreturn writeonly } +; IS__CGSCC_NPM: attributes #[[ATTR13]] = { willreturn } +; IS__CGSCC_NPM: attributes #[[ATTR14]] = { nounwind willreturn writeonly } +; IS__CGSCC_NPM: attributes #[[ATTR15]] = { nounwind } +; IS__CGSCC_NPM: attributes #[[ATTR16]] = { nosync nounwind } ;. ; IS__TUNIT____: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4} ; IS__TUNIT____: [[META1:![0-9]+]] = !{i32 7, !"uwtable", i32 1} diff --git a/llvm/test/Transforms/Attributor/value-simplify.ll b/llvm/test/Transforms/Attributor/value-simplify.ll --- a/llvm/test/Transforms/Attributor/value-simplify.ll +++ b/llvm/test/Transforms/Attributor/value-simplify.ll @@ -1289,7 +1289,7 @@ ; IS__CGSCC_OPM: attributes #[[ATTR3]] = { argmemonly nofree norecurse nosync nounwind writeonly } ; IS__CGSCC_OPM: attributes #[[ATTR4]] = { nofree norecurse nosync nounwind willreturn writeonly } ; IS__CGSCC_OPM: attributes #[[ATTR5]] = { willreturn } -; IS__CGSCC_OPM: attributes #[[ATTR6]] = { nounwind willreturn writeonly } +; IS__CGSCC_OPM: attributes #[[ATTR6]] = { norecurse nounwind willreturn writeonly } ;. ; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree nosync nounwind willreturn } ; IS__CGSCC_NPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn } diff --git a/llvm/test/Transforms/OpenMP/custom_state_machines.ll b/llvm/test/Transforms/OpenMP/custom_state_machines.ll --- a/llvm/test/Transforms/OpenMP/custom_state_machines.ll +++ b/llvm/test/Transforms/OpenMP/custom_state_machines.ll @@ -1584,9 +1584,9 @@ ; AMDGPU-NEXT: ret void ; ; -; AMDGPU: Function Attrs: convergent noinline nounwind +; AMDGPU: Function Attrs: convergent noinline norecurse nounwind ; AMDGPU-LABEL: define {{[^@]+}}@simple_state_machine_interprocedural_nested_recursive_after.internalized -; AMDGPU-SAME: (i32 [[A:%.*]]) #[[ATTR1]] { +; AMDGPU-SAME: (i32 [[A:%.*]]) #[[ATTR0]] { ; AMDGPU-NEXT: entry: ; AMDGPU-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 ; AMDGPU-NEXT: store i32 [[A]], i32* [[A_ADDR]], align 4 @@ -2512,9 +2512,9 @@ ; NVPTX-NEXT: ret void ; ; -; NVPTX: Function Attrs: convergent noinline nounwind +; NVPTX: Function Attrs: convergent noinline norecurse nounwind ; NVPTX-LABEL: define {{[^@]+}}@simple_state_machine_interprocedural_nested_recursive_after.internalized -; NVPTX-SAME: (i32 [[A:%.*]]) #[[ATTR1]] { +; NVPTX-SAME: (i32 [[A:%.*]]) #[[ATTR0]] { ; NVPTX-NEXT: entry: ; NVPTX-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 ; NVPTX-NEXT: store i32 [[A]], i32* [[A_ADDR]], align 4 @@ -3231,9 +3231,9 @@ ; AMDGPU-DISABLED-NEXT: ret void ; ; -; AMDGPU-DISABLED: Function Attrs: convergent noinline nounwind +; AMDGPU-DISABLED: Function Attrs: convergent noinline norecurse nounwind ; AMDGPU-DISABLED-LABEL: define {{[^@]+}}@simple_state_machine_interprocedural_nested_recursive_after.internalized -; AMDGPU-DISABLED-SAME: (i32 [[A:%.*]]) #[[ATTR1]] { +; AMDGPU-DISABLED-SAME: (i32 [[A:%.*]]) #[[ATTR0]] { ; AMDGPU-DISABLED-NEXT: entry: ; AMDGPU-DISABLED-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 ; AMDGPU-DISABLED-NEXT: store i32 [[A]], i32* [[A_ADDR]], align 4 @@ -3926,9 +3926,9 @@ ; NVPTX-DISABLED-NEXT: ret void ; ; -; NVPTX-DISABLED: Function Attrs: convergent noinline nounwind +; NVPTX-DISABLED: Function Attrs: convergent noinline norecurse nounwind ; NVPTX-DISABLED-LABEL: define {{[^@]+}}@simple_state_machine_interprocedural_nested_recursive_after.internalized -; NVPTX-DISABLED-SAME: (i32 [[A:%.*]]) #[[ATTR1]] { +; NVPTX-DISABLED-SAME: (i32 [[A:%.*]]) #[[ATTR0]] { ; NVPTX-DISABLED-NEXT: entry: ; NVPTX-DISABLED-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 ; NVPTX-DISABLED-NEXT: store i32 [[A]], i32* [[A_ADDR]], align 4