aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms/IPO/FunctionAttrs.cpp
diff options
context:
space:
mode:
authorNick Lewycky <nicholas@mxc.ca>2009-01-02 03:46:56 +0000
committerNick Lewycky <nicholas@mxc.ca>2009-01-02 03:46:56 +0000
commit6b0568628319e08b36b8ec14793083e6bbf101a7 (patch)
tree4e600f6b3b7547f0ec7c9786d81dceef6612ed5b /lib/Transforms/IPO/FunctionAttrs.cpp
parentb9b3a702c46f5f22364d07f26f20ad8b9fe97f34 (diff)
Make adding nocapture a bit stronger. FreeInst is nocapture. Also,
functions that don't write can't leak a pointer except through the return value, so a void readonly function is implicitly nocapture. Test these, and add a test that verifies that f1 calling f2 with an otherwise dead pointer gets both of them marked nocapture. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@61552 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/IPO/FunctionAttrs.cpp')
-rw-r--r--lib/Transforms/IPO/FunctionAttrs.cpp30
1 files changed, 27 insertions, 3 deletions
diff --git a/lib/Transforms/IPO/FunctionAttrs.cpp b/lib/Transforms/IPO/FunctionAttrs.cpp
index fcdede2fa3..3c9570bd50 100644
--- a/lib/Transforms/IPO/FunctionAttrs.cpp
+++ b/lib/Transforms/IPO/FunctionAttrs.cpp
@@ -208,10 +208,20 @@ bool FunctionAttrs::isCaptured(Function &F, Value *V) {
continue;
}
+ if (isa<FreeInst>(I)) {
+ // Freeing a pointer does not cause it to escape.
+ continue;
+ }
+
CallSite CS = CallSite::get(I);
if (CS.getInstruction()) {
- // Does not escape if only passed via 'nocapture' arguments. Note
- // that calling a function pointer does not in itself cause that
+ // Does not escape if the callee is readonly and doesn't return a
+ // copy through its own return value.
+ if (CS.onlyReadsMemory() && I->getType() == Type::VoidTy)
+ continue;
+
+ // Does not escape if passed via 'nocapture' arguments. Note that
+ // calling a function pointer does not in itself cause that
// function pointer to escape. This is a subtle point considering
// that (for example) the callee might return its own address. It
// is analogous to saying that loading a value from a pointer does
@@ -264,6 +274,20 @@ bool FunctionAttrs::AddNoCaptureAttrs(const std::vector<CallGraphNode *> &SCC) {
// External node - skip it;
continue;
+ // If the function is readonly and doesn't return any value, we
+ // know that the pointer value can't escape. Mark all of its pointer
+ // arguments nocapture.
+ if (F->onlyReadsMemory() && F->getReturnType() == Type::VoidTy) {
+ for (Function::arg_iterator A = F->arg_begin(), E = F->arg_end();
+ A != E; ++A)
+ if (isa<PointerType>(A->getType()) && !A->hasNoCaptureAttr()) {
+ A->addAttr(Attribute::NoCapture);
+ ++NumNoCapture;
+ Changed = true;
+ }
+ continue;
+ }
+
// Definitions with weak linkage may be overridden at linktime with
// something that writes memory, so treat them like declarations.
if (F->isDeclaration() || F->mayBeOverridden())
@@ -273,7 +297,7 @@ bool FunctionAttrs::AddNoCaptureAttrs(const std::vector<CallGraphNode *> &SCC) {
if (isa<PointerType>(A->getType()) && !A->hasNoCaptureAttr() &&
!isCaptured(*F, A)) {
A->addAttr(Attribute::NoCapture);
- NumNoCapture++;
+ ++NumNoCapture;
Changed = true;
}
}