1
0
mirror of https://github.com/c64scene-ar/llvm-6502.git synced 2025-04-12 23:37:33 +00:00

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
This commit is contained in:
Rafael Espindola 2011-10-05 20:05:13 +00:00
parent 30c1ff234d
commit 11f1a8335e
3 changed files with 45 additions and 14 deletions
include/llvm
lib/VMCore
test/Transforms/TailCallElim

@ -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);

@ -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 <rdar://problem/8031714> 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<CallInst>(*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<CallInst>(&*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;
}

@ -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