aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms/IPO/FunctionAttrs.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-01-02 19:17:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-01-02 19:17:04 +0000
commitb915e9e0fc85ba6f398b3fab0db6a81a8913af94 (patch)
tree98b8f811c7aff2547cab8642daf372d6c59502fb /lib/Transforms/IPO/FunctionAttrs.cpp
parent6421cca32f69ac849537a3cff78c352195e99f1b (diff)
downloadsrc-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.cpp103
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;