From: Rafael Espindola Date: Wed, 5 Oct 2011 20:05:13 +0000 (+0000) Subject: Check for the returns_twice attribute in callsFunctionThatReturnsTwice. This X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=11f1a8335e207971f66eb60609e16b8719be5450;p=oota-llvm.git Check for the returns_twice attribute in callsFunctionThatReturnsTwice. This fixes PR11038, but there are still some cleanups to be done. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141204 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h index 2f879a18617..23e3e7e0f7b 100644 --- a/include/llvm/Instructions.h +++ b/include/llvm/Instructions.h @@ -1267,6 +1267,15 @@ public: else removeAttribute(~0, Attribute::NoInline); } + /// @brief Return true if the call can return twice + bool canReturnTwice() const { + return paramHasAttr(~0, Attribute::ReturnsTwice); + } + void setCanReturnTwice(bool Value = true) { + if (Value) addAttribute(~0, Attribute::ReturnsTwice); + else removeAttribute(~0, Attribute::ReturnsTwice); + } + /// @brief Determine if the call does not access memory. bool doesNotAccessMemory() const { return paramHasAttr(~0, Attribute::ReadNone); diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp index 1f59bf97167..ef0827b110e 100644 --- a/lib/VMCore/Function.cpp +++ b/lib/VMCore/Function.cpp @@ -17,6 +17,7 @@ #include "llvm/LLVMContext.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/Support/CallSite.h" +#include "llvm/Support/InstIterator.h" #include "llvm/Support/LeakDetector.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/StringPool.h" @@ -416,7 +417,6 @@ bool Function::hasAddressTaken(const User* *PutOffender) const { /// FIXME: Remove after is fixed. /// FIXME: Is the above FIXME valid? bool Function::callsFunctionThatReturnsTwice() const { - const Module *M = this->getParent(); static const char *ReturnsTwiceFns[] = { "_setjmp", "setjmp", @@ -428,16 +428,25 @@ bool Function::callsFunctionThatReturnsTwice() const { "getcontext" }; - for (unsigned I = 0; I < array_lengthof(ReturnsTwiceFns); ++I) - if (const Function *Callee = M->getFunction(ReturnsTwiceFns[I])) { - if (!Callee->use_empty()) - for (Value::const_use_iterator - I = Callee->use_begin(), E = Callee->use_end(); - I != E; ++I) - if (const CallInst *CI = dyn_cast(*I)) - if (CI->getParent()->getParent() == this) - return true; + for (const_inst_iterator I = inst_begin(this), E = inst_end(this); I != E; + ++I) { + const CallInst* callInst = dyn_cast(&*I); + if (!callInst) + continue; + if (callInst->canReturnTwice()) + return true; + + // check for known function names. + // FIXME: move this to clang. + Function *F = callInst->getCalledFunction(); + if (!F) + continue; + StringRef Name = F->getName(); + for (unsigned J = 0; J < array_lengthof(ReturnsTwiceFns); ++J) { + if (Name == ReturnsTwiceFns[J]) + return true; } + } return false; } diff --git a/test/Transforms/TailCallElim/setjmp.ll b/test/Transforms/TailCallElim/setjmp.ll index 35bb75dddb3..7ef9cb360f5 100644 --- a/test/Transforms/TailCallElim/setjmp.ll +++ b/test/Transforms/TailCallElim/setjmp.ll @@ -1,16 +1,29 @@ ; RUN: opt < %s -tailcallelim -S | FileCheck %s -; Test that we don't tail call in a functions that calls setjmp. +; Test that we don't tail call in a functions that calls returns_twice +; functions. +declare void @bar() + +; CHECK: foo1 ; CHECK-NOT: tail call void @bar() -define void @foo(i32* %x) { +define void @foo1(i32* %x) { bb: %tmp75 = tail call i32 @setjmp(i32* %x) call void @bar() ret void } -declare i32 @setjmp(i32*) returns_twice +declare i32 @setjmp(i32*) -declare void @bar() +; CHECK: foo2 +; CHECK-NOT: tail call void @bar() + +define void @foo2(i32* %x) { +bb: + %tmp75 = tail call i32 @zed2(i32* %x) + call void @bar() + ret void +} +declare i32 @zed2(i32*) returns_twice