diff --git a/llvm/docs/LangRef.html b/llvm/docs/LangRef.html index 0ec08eb0a058..7882da67e1aa 100644 --- a/llvm/docs/LangRef.html +++ b/llvm/docs/LangRef.html @@ -1262,6 +1262,11 @@ define void @f() optsize { ... } the ELF x86-64 abi, but it can be disabled for some compilation units. +
returns_twice
+
This attribute indicates that this function can return + twice. The C setjmp is an example of such a function. + The compiler disables some optimizations (like tail calls) in the caller of + these functions.
diff --git a/llvm/include/llvm/Attributes.h b/llvm/include/llvm/Attributes.h index cd3ee35d7497..2d7b33b29bcf 100644 --- a/llvm/include/llvm/Attributes.h +++ b/llvm/include/llvm/Attributes.h @@ -65,8 +65,7 @@ const Attributes StackAlignment = 7<<26; ///< Alignment of stack for ///of alignment with +1 bias ///0 means unaligned (different from ///alignstack(1)) -const Attributes Hotpatch = 1<<29; ///< Function should have special - ///'hotpatch' sequence in prologue +const Attributes ReturnsTwice = 1<<29; ///< Function can return twice const Attributes UWTable = 1<<30; ///< Function must be in a unwind ///table const Attributes NonLazyBind = 1U<<31; ///< Function is called early and/or @@ -93,7 +92,7 @@ const Attributes ParameterOnly = ByVal | Nest | StructRet | NoCapture; const Attributes FunctionOnly = NoReturn | NoUnwind | ReadNone | ReadOnly | NoInline | AlwaysInline | OptimizeForSize | StackProtect | StackProtectReq | NoRedZone | NoImplicitFloat | Naked | InlineHint | StackAlignment | - Hotpatch | UWTable | NonLazyBind; + UWTable | NonLazyBind | ReturnsTwice; /// @brief Parameter attributes that do not apply to vararg call arguments. const Attributes VarArgsIncompatible = StructRet; diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index fdadd1ba93f6..029f9426f683 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -558,6 +558,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(readnone); KEYWORD(readonly); KEYWORD(uwtable); + KEYWORD(returns_twice); KEYWORD(inlinehint); KEYWORD(noinline); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 4d233cab6fbe..cafaab01afd9 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -911,6 +911,7 @@ bool LLParser::ParseOptionalAttrs(unsigned &Attrs, unsigned AttrKind) { case lltok::kw_noreturn: Attrs |= Attribute::NoReturn; break; case lltok::kw_nounwind: Attrs |= Attribute::NoUnwind; break; case lltok::kw_uwtable: Attrs |= Attribute::UWTable; break; + case lltok::kw_returns_twice: Attrs |= Attribute::ReturnsTwice; break; case lltok::kw_noinline: Attrs |= Attribute::NoInline; break; case lltok::kw_readnone: Attrs |= Attribute::ReadNone; break; case lltok::kw_readonly: Attrs |= Attribute::ReadOnly; break; @@ -922,7 +923,6 @@ bool LLParser::ParseOptionalAttrs(unsigned &Attrs, unsigned AttrKind) { case lltok::kw_noredzone: Attrs |= Attribute::NoRedZone; break; case lltok::kw_noimplicitfloat: Attrs |= Attribute::NoImplicitFloat; break; case lltok::kw_naked: Attrs |= Attribute::Naked; break; - case lltok::kw_hotpatch: Attrs |= Attribute::Hotpatch; break; case lltok::kw_nonlazybind: Attrs |= Attribute::NonLazyBind; break; case lltok::kw_alignstack: { diff --git a/llvm/lib/AsmParser/LLToken.h b/llvm/lib/AsmParser/LLToken.h index d22ecf31bdae..acdd4b8ebf83 100644 --- a/llvm/lib/AsmParser/LLToken.h +++ b/llvm/lib/AsmParser/LLToken.h @@ -90,6 +90,7 @@ namespace lltok { kw_readnone, kw_readonly, kw_uwtable, + kw_returns_twice, kw_inlinehint, kw_noinline, diff --git a/llvm/lib/Target/CppBackend/CPPBackend.cpp b/llvm/lib/Target/CppBackend/CPPBackend.cpp index 16401a8f98b9..9a6ff3292ab6 100644 --- a/llvm/lib/Target/CppBackend/CPPBackend.cpp +++ b/llvm/lib/Target/CppBackend/CPPBackend.cpp @@ -470,7 +470,7 @@ void CppWriter::printAttributes(const AttrListPtr &PAL, HANDLE_ATTR(NoImplicitFloat); HANDLE_ATTR(Naked); HANDLE_ATTR(InlineHint); - HANDLE_ATTR(Hotpatch); + HANDLE_ATTR(ReturnsTwice); HANDLE_ATTR(UWTable); HANDLE_ATTR(NonLazyBind); #undef HANDLE_ATTR diff --git a/llvm/lib/VMCore/Attributes.cpp b/llvm/lib/VMCore/Attributes.cpp index b728b9284b44..485be75d1b12 100644 --- a/llvm/lib/VMCore/Attributes.cpp +++ b/llvm/lib/VMCore/Attributes.cpp @@ -38,6 +38,8 @@ std::string Attribute::getAsString(Attributes Attrs) { Result += "nounwind "; if (Attrs & Attribute::UWTable) Result += "uwtable "; + if (Attrs & Attribute::ReturnsTwice) + Result += "returns_twice "; if (Attrs & Attribute::InReg) Result += "inreg "; if (Attrs & Attribute::NoAlias) @@ -72,8 +74,6 @@ std::string Attribute::getAsString(Attributes Attrs) { Result += "noimplicitfloat "; if (Attrs & Attribute::Naked) Result += "naked "; - if (Attrs & Attribute::Hotpatch) - Result += "hotpatch "; if (Attrs & Attribute::NonLazyBind) Result += "nonlazybind "; if (Attrs & Attribute::StackAlignment) { diff --git a/llvm/test/Transforms/Mem2Reg/2007-08-27-VolatileLoadsStores.ll b/llvm/test/Transforms/Mem2Reg/2007-08-27-VolatileLoadsStores.ll index 50683cf8baa0..52a837531296 100644 --- a/llvm/test/Transforms/Mem2Reg/2007-08-27-VolatileLoadsStores.ll +++ b/llvm/test/Transforms/Mem2Reg/2007-08-27-VolatileLoadsStores.ll @@ -42,6 +42,6 @@ return: ; preds = %bb6 ret i32 %retval8 } -declare i32 @_setjmp(%struct.__jmp_buf_tag*) +declare i32 @_setjmp(%struct.__jmp_buf_tag*) returns_twice declare void @g() diff --git a/llvm/test/Transforms/TailCallElim/setjmp.ll b/llvm/test/Transforms/TailCallElim/setjmp.ll index 7b7fe568259e..35bb75dddb30 100644 --- a/llvm/test/Transforms/TailCallElim/setjmp.ll +++ b/llvm/test/Transforms/TailCallElim/setjmp.ll @@ -11,6 +11,6 @@ bb: ret void } -declare i32 @setjmp(i32*) +declare i32 @setjmp(i32*) returns_twice declare void @bar()