diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:17:04 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:17:04 +0000 |
commit | b915e9e0fc85ba6f398b3fab0db6a81a8913af94 (patch) | |
tree | 98b8f811c7aff2547cab8642daf372d6c59502fb /lib/Transforms/IPO/FunctionAttrs.cpp | |
parent | 6421cca32f69ac849537a3cff78c352195e99f1b (diff) | |
download | src-b915e9e0fc85ba6f398b3fab0db6a81a8913af94.tar.gz src-b915e9e0fc85ba6f398b3fab0db6a81a8913af94.zip |
Vendor import of llvm trunk r290819:vendor/llvm/llvm-trunk-r290819
Notes
Notes:
svn path=/vendor/llvm/dist/; revision=311116
svn path=/vendor/llvm/llvm-trunk-r290819/; revision=311117; tag=vendor/llvm/llvm-trunk-r290819
Diffstat (limited to 'lib/Transforms/IPO/FunctionAttrs.cpp')
-rw-r--r-- | lib/Transforms/IPO/FunctionAttrs.cpp | 103 |
1 files changed, 83 insertions, 20 deletions
diff --git a/lib/Transforms/IPO/FunctionAttrs.cpp b/lib/Transforms/IPO/FunctionAttrs.cpp index 787f4342831d..402a66552c24 100644 --- a/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/lib/Transforms/IPO/FunctionAttrs.cpp @@ -42,6 +42,7 @@ using namespace llvm; STATISTIC(NumReadNone, "Number of functions marked readnone"); STATISTIC(NumReadOnly, "Number of functions marked readonly"); STATISTIC(NumNoCapture, "Number of arguments marked nocapture"); +STATISTIC(NumReturned, "Number of arguments marked returned"); STATISTIC(NumReadNoneArg, "Number of arguments marked readnone"); STATISTIC(NumReadOnlyArg, "Number of arguments marked readonly"); STATISTIC(NumNoAlias, "Number of function returns marked noalias"); @@ -331,23 +332,16 @@ struct ArgumentUsesTracker : public CaptureTracker { namespace llvm { template <> struct GraphTraits<ArgumentGraphNode *> { - typedef ArgumentGraphNode NodeType; typedef ArgumentGraphNode *NodeRef; typedef SmallVectorImpl<ArgumentGraphNode *>::iterator ChildIteratorType; - static inline NodeType *getEntryNode(NodeType *A) { return A; } - static inline ChildIteratorType child_begin(NodeType *N) { - return N->Uses.begin(); - } - static inline ChildIteratorType child_end(NodeType *N) { - return N->Uses.end(); - } + static NodeRef getEntryNode(NodeRef A) { return A; } + static ChildIteratorType child_begin(NodeRef N) { return N->Uses.begin(); } + static ChildIteratorType child_end(NodeRef N) { return N->Uses.end(); } }; template <> struct GraphTraits<ArgumentGraph *> : public GraphTraits<ArgumentGraphNode *> { - static NodeType *getEntryNode(ArgumentGraph *AG) { - return AG->getEntryNode(); - } + static NodeRef getEntryNode(ArgumentGraph *AG) { return AG->getEntryNode(); } static ChildIteratorType nodes_begin(ArgumentGraph *AG) { return AG->begin(); } @@ -447,8 +441,8 @@ determinePointerReadAttrs(Argument *A, // to a operand bundle use, these cannot participate in the optimistic SCC // analysis. Instead, we model the operand bundle uses as arguments in // call to a function external to the SCC. - if (!SCCNodes.count(&*std::next(F->arg_begin(), UseIndex)) || - IsOperandBundleUse) { + if (IsOperandBundleUse || + !SCCNodes.count(&*std::next(F->arg_begin(), UseIndex))) { // The accessors used on CallSite here do the right thing for calls and // invokes with operand bundles. @@ -484,6 +478,59 @@ determinePointerReadAttrs(Argument *A, return IsRead ? Attribute::ReadOnly : Attribute::ReadNone; } +/// Deduce returned attributes for the SCC. +static bool addArgumentReturnedAttrs(const SCCNodeSet &SCCNodes) { + bool Changed = false; + + AttrBuilder B; + B.addAttribute(Attribute::Returned); + + // Check each function in turn, determining if an argument is always returned. + for (Function *F : SCCNodes) { + // We can infer and propagate function attributes only when we know that the + // definition we'll get at link time is *exactly* the definition we see now. + // For more details, see GlobalValue::mayBeDerefined. + if (!F->hasExactDefinition()) + continue; + + if (F->getReturnType()->isVoidTy()) + continue; + + // There is nothing to do if an argument is already marked as 'returned'. + if (any_of(F->args(), + [](const Argument &Arg) { return Arg.hasReturnedAttr(); })) + continue; + + auto FindRetArg = [&]() -> Value * { + Value *RetArg = nullptr; + for (BasicBlock &BB : *F) + if (auto *Ret = dyn_cast<ReturnInst>(BB.getTerminator())) { + // Note that stripPointerCasts should look through functions with + // returned arguments. + Value *RetVal = Ret->getReturnValue()->stripPointerCasts(); + if (!isa<Argument>(RetVal) || RetVal->getType() != F->getReturnType()) + return nullptr; + + if (!RetArg) + RetArg = RetVal; + else if (RetArg != RetVal) + return nullptr; + } + + return RetArg; + }; + + if (Value *RetArg = FindRetArg()) { + auto *A = cast<Argument>(RetArg); + A->addAttr(AttributeSet::get(F->getContext(), A->getArgNo() + 1, B)); + ++NumReturned; + Changed = true; + } + } + + return Changed; +} + /// Deduce nocapture attributes for the SCC. static bool addArgumentAttrs(const SCCNodeSet &SCCNodes) { bool Changed = false; @@ -726,7 +773,8 @@ static bool isFunctionMallocLike(Function *F, const SCCNodeSet &SCCNodes) { break; if (CS.getCalledFunction() && SCCNodes.count(CS.getCalledFunction())) break; - } // fall-through + LLVM_FALLTHROUGH; + } default: return false; // Did not come from an allocation. } @@ -986,9 +1034,11 @@ static bool addNoRecurseAttrs(const SCCNodeSet &SCCNodes) { } PreservedAnalyses PostOrderFunctionAttrsPass::run(LazyCallGraph::SCC &C, - CGSCCAnalysisManager &AM) { + CGSCCAnalysisManager &AM, + LazyCallGraph &CG, + CGSCCUpdateResult &) { FunctionAnalysisManager &FAM = - AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C).getManager(); + AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager(); // We pass a lambda into functions to wire them up to the analysis manager // for getting function analyses. @@ -1025,6 +1075,7 @@ PreservedAnalyses PostOrderFunctionAttrsPass::run(LazyCallGraph::SCC &C, } bool Changed = false; + Changed |= addArgumentReturnedAttrs(SCCNodes); Changed |= addReadAttrs(SCCNodes, AARGetter); Changed |= addArgumentAttrs(SCCNodes); @@ -1044,7 +1095,8 @@ namespace { struct PostOrderFunctionAttrsLegacyPass : public CallGraphSCCPass { static char ID; // Pass identification, replacement for typeid PostOrderFunctionAttrsLegacyPass() : CallGraphSCCPass(ID) { - initializePostOrderFunctionAttrsLegacyPassPass(*PassRegistry::getPassRegistry()); + initializePostOrderFunctionAttrsLegacyPassPass( + *PassRegistry::getPassRegistry()); } bool runOnSCC(CallGraphSCC &SCC) override; @@ -1066,7 +1118,9 @@ INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass) INITIALIZE_PASS_END(PostOrderFunctionAttrsLegacyPass, "functionattrs", "Deduce function attributes", false, false) -Pass *llvm::createPostOrderFunctionAttrsLegacyPass() { return new PostOrderFunctionAttrsLegacyPass(); } +Pass *llvm::createPostOrderFunctionAttrsLegacyPass() { + return new PostOrderFunctionAttrsLegacyPass(); +} template <typename AARGetterT> static bool runImpl(CallGraphSCC &SCC, AARGetterT AARGetter) { @@ -1090,6 +1144,7 @@ static bool runImpl(CallGraphSCC &SCC, AARGetterT AARGetter) { SCCNodes.insert(F); } + Changed |= addArgumentReturnedAttrs(SCCNodes); Changed |= addReadAttrs(SCCNodes, AARGetter); Changed |= addArgumentAttrs(SCCNodes); @@ -1127,7 +1182,8 @@ namespace { struct ReversePostOrderFunctionAttrsLegacyPass : public ModulePass { static char ID; // Pass identification, replacement for typeid ReversePostOrderFunctionAttrsLegacyPass() : ModulePass(ID) { - initializeReversePostOrderFunctionAttrsLegacyPassPass(*PassRegistry::getPassRegistry()); + initializeReversePostOrderFunctionAttrsLegacyPassPass( + *PassRegistry::getPassRegistry()); } bool runOnModule(Module &M) override; @@ -1216,10 +1272,17 @@ bool ReversePostOrderFunctionAttrsLegacyPass::runOnModule(Module &M) { } PreservedAnalyses -ReversePostOrderFunctionAttrsPass::run(Module &M, AnalysisManager<Module> &AM) { +ReversePostOrderFunctionAttrsPass::run(Module &M, ModuleAnalysisManager &AM) { auto &CG = AM.getResult<CallGraphAnalysis>(M); bool Changed = deduceFunctionAttributeInRPO(M, CG); + + // CallGraphAnalysis holds AssertingVH and must be invalidated eagerly so + // that other passes don't delete stuff from under it. + // FIXME: We need to invalidate this to avoid PR28400. Is there a better + // solution? + AM.invalidate<CallGraphAnalysis>(M); + if (!Changed) return PreservedAnalyses::all(); PreservedAnalyses PA; |