From: Nick Lewycky Date: Fri, 2 Jan 2009 03:46:56 +0000 (+0000) Subject: Make adding nocapture a bit stronger. FreeInst is nocapture. Also, X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=6b0568628319e08b36b8ec14793083e6bbf101a7;p=oota-llvm.git 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 --- diff --git a/lib/Transforms/IPO/FunctionAttrs.cpp b/lib/Transforms/IPO/FunctionAttrs.cpp index fcdede2fa35..3c9570bd508 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(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 &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(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 &SCC) { if (isa(A->getType()) && !A->hasNoCaptureAttr() && !isCaptured(*F, A)) { A->addAttr(Attribute::NoCapture); - NumNoCapture++; + ++NumNoCapture; Changed = true; } } diff --git a/test/Transforms/FunctionAttrs/2008-12-31-NoCapture.ll b/test/Transforms/FunctionAttrs/2008-12-31-NoCapture.ll index 61c607dc007..758f0dd3add 100644 --- a/test/Transforms/FunctionAttrs/2008-12-31-NoCapture.ll +++ b/test/Transforms/FunctionAttrs/2008-12-31-NoCapture.ll @@ -1,5 +1,5 @@ ; RUN: llvm-as < %s | opt -functionattrs | llvm-dis | not grep {nocapture *%%q} -; RUN: llvm-as < %s | opt -functionattrs | llvm-dis | grep {nocapture *%%p} | count 3 +; RUN: llvm-as < %s | opt -functionattrs | llvm-dis | grep {nocapture *%%p} | count 8 @g = global i32* null ; [#uses=1] define i32* @c1(i32* %q) { @@ -62,3 +62,25 @@ define void @nc3(void ()* %p) { call void %p() ret void } + +declare void @external(i8*) readonly +define void @nc4(i8* %p) { + call void @external(i8* %p) + ret void +} + +define void @nc5(void (i8*)* %f, i8* %p) { + call void %f(i8* %p) readonly + call void %f(i8* nocapture %p) + ret void +} + +define void @nc6(i8* %p) { + call void @nc7(i8* %p) + ret void +} + +define void @nc7(i8* %p) { + call void @nc6(i8* %p) + ret void +}