mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-23 20:34:58 +00:00
Add a new attribute: norecurse
This attribute allows the compiler to assume that the function never recurses into itself, either directly or indirectly (transitively). This can be used among other things to demote global variables to locals. llvm-svn: 252282
This commit is contained in:
parent
34cc3b400b
commit
be569ad3b9
@ -1277,6 +1277,10 @@ example:
|
||||
This function attribute indicates that the function never returns
|
||||
normally. This produces undefined behavior at runtime if the
|
||||
function ever does dynamically return.
|
||||
``norecurse``
|
||||
This function attribute indicates that the function does not call itself
|
||||
either directly or indirectly down any possible call path. This produces
|
||||
undefined behavior at runtime if the function ever does recurse.
|
||||
``nounwind``
|
||||
This function attribute indicates that the function never raises an
|
||||
exception. If the function does raise an exception, its runtime
|
||||
|
@ -466,7 +466,8 @@ enum { BITCODE_CURRENT_EPOCH = 0 };
|
||||
ATTR_KIND_SAFESTACK = 44,
|
||||
ATTR_KIND_ARGMEMONLY = 45,
|
||||
ATTR_KIND_SWIFT_SELF = 46,
|
||||
ATTR_KIND_SWIFT_ERROR = 47
|
||||
ATTR_KIND_SWIFT_ERROR = 47,
|
||||
ATTR_KIND_NO_RECURSE = 48
|
||||
};
|
||||
|
||||
enum ComdatSelectionKindCodes {
|
||||
|
@ -86,6 +86,7 @@ public:
|
||||
NoDuplicate, ///< Call cannot be duplicated
|
||||
NoImplicitFloat, ///< Disable implicit floating point insts
|
||||
NoInline, ///< inline=never
|
||||
NoRecurse, ///< The function does not recurse
|
||||
NonLazyBind, ///< Function is called early and/or
|
||||
///< often, so lazy binding isn't worthwhile
|
||||
NonNull, ///< Pointer is known to be not null
|
||||
|
@ -329,6 +329,15 @@ public:
|
||||
addFnAttr(Attribute::Convergent);
|
||||
}
|
||||
|
||||
/// Determine if the function is known not to recurse, directly or
|
||||
/// indirectly.
|
||||
bool doesNotRecurse() const {
|
||||
return AttributeSets.hasAttribute(AttributeSet::FunctionIndex,
|
||||
Attribute::NoRecurse);
|
||||
}
|
||||
void setDoesNotRecurse() {
|
||||
addFnAttr(Attribute::NoRecurse);
|
||||
}
|
||||
|
||||
/// @brief True if the ABI mandates (or the user requested) that this
|
||||
/// function be in a unwind table.
|
||||
|
@ -616,6 +616,7 @@ lltok::Kind LLLexer::LexIdentifier() {
|
||||
KEYWORD(noduplicate);
|
||||
KEYWORD(noimplicitfloat);
|
||||
KEYWORD(noinline);
|
||||
KEYWORD(norecurse);
|
||||
KEYWORD(nonlazybind);
|
||||
KEYWORD(nonnull);
|
||||
KEYWORD(noredzone);
|
||||
|
@ -998,6 +998,7 @@ bool LLParser::ParseFnAttributeValuePairs(AttrBuilder &B,
|
||||
case lltok::kw_nonlazybind: B.addAttribute(Attribute::NonLazyBind); break;
|
||||
case lltok::kw_noredzone: B.addAttribute(Attribute::NoRedZone); break;
|
||||
case lltok::kw_noreturn: B.addAttribute(Attribute::NoReturn); break;
|
||||
case lltok::kw_norecurse: B.addAttribute(Attribute::NoRecurse); break;
|
||||
case lltok::kw_nounwind: B.addAttribute(Attribute::NoUnwind); break;
|
||||
case lltok::kw_optnone: B.addAttribute(Attribute::OptimizeNone); break;
|
||||
case lltok::kw_optsize: B.addAttribute(Attribute::OptimizeForSize); break;
|
||||
|
@ -123,6 +123,7 @@ namespace lltok {
|
||||
kw_noduplicate,
|
||||
kw_noimplicitfloat,
|
||||
kw_noinline,
|
||||
kw_norecurse,
|
||||
kw_nonlazybind,
|
||||
kw_nonnull,
|
||||
kw_noredzone,
|
||||
|
@ -1305,6 +1305,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) {
|
||||
return Attribute::NoImplicitFloat;
|
||||
case bitc::ATTR_KIND_NO_INLINE:
|
||||
return Attribute::NoInline;
|
||||
case bitc::ATTR_KIND_NO_RECURSE:
|
||||
return Attribute::NoRecurse;
|
||||
case bitc::ATTR_KIND_NON_LAZY_BIND:
|
||||
return Attribute::NonLazyBind;
|
||||
case bitc::ATTR_KIND_NON_NULL:
|
||||
|
@ -202,6 +202,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) {
|
||||
return bitc::ATTR_KIND_NO_IMPLICIT_FLOAT;
|
||||
case Attribute::NoInline:
|
||||
return bitc::ATTR_KIND_NO_INLINE;
|
||||
case Attribute::NoRecurse:
|
||||
return bitc::ATTR_KIND_NO_RECURSE;
|
||||
case Attribute::NonLazyBind:
|
||||
return bitc::ATTR_KIND_NON_LAZY_BIND;
|
||||
case Attribute::NonNull:
|
||||
|
@ -232,6 +232,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
|
||||
return "noredzone";
|
||||
if (hasAttribute(Attribute::NoReturn))
|
||||
return "noreturn";
|
||||
if (hasAttribute(Attribute::NoRecurse))
|
||||
return "norecurse";
|
||||
if (hasAttribute(Attribute::NoUnwind))
|
||||
return "nounwind";
|
||||
if (hasAttribute(Attribute::OptimizeNone))
|
||||
@ -442,6 +444,7 @@ uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) {
|
||||
case Attribute::JumpTable: return 1ULL << 45;
|
||||
case Attribute::Convergent: return 1ULL << 46;
|
||||
case Attribute::SafeStack: return 1ULL << 47;
|
||||
case Attribute::NoRecurse: return 1ULL << 48;
|
||||
case Attribute::Dereferenceable:
|
||||
llvm_unreachable("dereferenceable attribute not supported in raw format");
|
||||
break;
|
||||
|
@ -1233,7 +1233,8 @@ void Verifier::VerifyAttributeTypes(AttributeSet Attrs, unsigned Idx,
|
||||
I->getKindAsEnum() == Attribute::OptimizeNone ||
|
||||
I->getKindAsEnum() == Attribute::JumpTable ||
|
||||
I->getKindAsEnum() == Attribute::Convergent ||
|
||||
I->getKindAsEnum() == Attribute::ArgMemOnly) {
|
||||
I->getKindAsEnum() == Attribute::ArgMemOnly ||
|
||||
I->getKindAsEnum() == Attribute::NoRecurse) {
|
||||
if (!isFunction) {
|
||||
CheckFailed("Attribute '" + I->getAsString() +
|
||||
"' only applies to functions!", V);
|
||||
|
Binary file not shown.
@ -1,3 +1,3 @@
|
||||
; RUN: not llvm-c-test --module-dump < %S/Inputs/invalid.ll.bc 2>&1 | FileCheck %s
|
||||
|
||||
CHECK: Error parsing bitcode: Unknown attribute kind (48)
|
||||
CHECK: Error parsing bitcode: Unknown attribute kind (50)
|
||||
|
@ -204,7 +204,7 @@ define void @f34()
|
||||
; CHECK: define void @f34()
|
||||
{
|
||||
call void @nobuiltin() nobuiltin
|
||||
; CHECK: call void @nobuiltin() #27
|
||||
; CHECK: call void @nobuiltin() #28
|
||||
ret void;
|
||||
}
|
||||
|
||||
@ -272,6 +272,11 @@ define "string_attribute_with_value"="value" void @f46(i32 "string_attribute_wit
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK: define void @f47() #27
|
||||
define void @f47() norecurse {
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK: attributes #0 = { noreturn }
|
||||
; CHECK: attributes #1 = { nounwind }
|
||||
; CHECK: attributes #2 = { readnone }
|
||||
@ -299,4 +304,5 @@ define "string_attribute_with_value"="value" void @f46(i32 "string_attribute_wit
|
||||
; CHECK: attributes #24 = { jumptable }
|
||||
; CHECK: attributes #25 = { convergent }
|
||||
; CHECK: attributes #26 = { argmemonly }
|
||||
; CHECK: attributes #27 = { nobuiltin }
|
||||
; CHECK: attributes #27 = { norecurse }
|
||||
; CHECK: attributes #28 = { nobuiltin }
|
||||
|
@ -501,6 +501,8 @@ declare void @f.uwtable() uwtable
|
||||
; CHECK: declare void @f.uwtable() #30
|
||||
declare void @f.kvpair() "cpu"="cortex-a8"
|
||||
; CHECK:declare void @f.kvpair() #31
|
||||
declare void @f.norecurse() norecurse
|
||||
; CHECK: declare void @f.norecurse() #32
|
||||
|
||||
; Functions -- section
|
||||
declare void @f.section() section "80"
|
||||
@ -559,7 +561,7 @@ declare void @f.prologuearray() prologue [4 x i32] [i32 0, i32 1, i32 2, i32 3]
|
||||
|
||||
; Functions -- Personality constant
|
||||
declare void @llvm.donothing() nounwind readnone
|
||||
; CHECK: declare void @llvm.donothing() #32
|
||||
; CHECK: declare void @llvm.donothing() #33
|
||||
define void @f.no_personality() personality i8 3 {
|
||||
; CHECK: define void @f.no_personality() personality i8 3
|
||||
invoke void @llvm.donothing() to label %normal unwind label %exception
|
||||
@ -1125,7 +1127,7 @@ exit:
|
||||
; CHECK: select <2 x i1> <i1 true, i1 false>, <2 x i8> <i8 2, i8 3>, <2 x i8> <i8 3, i8 2>
|
||||
|
||||
call void @f.nobuiltin() builtin
|
||||
; CHECK: call void @f.nobuiltin() #36
|
||||
; CHECK: call void @f.nobuiltin() #37
|
||||
|
||||
call fastcc noalias i32* @f.noalias() noinline
|
||||
; CHECK: call fastcc noalias i32* @f.noalias() #12
|
||||
@ -1497,11 +1499,12 @@ normal:
|
||||
; CHECK: attributes #29 = { "thunk" }
|
||||
; CHECK: attributes #30 = { uwtable }
|
||||
; CHECK: attributes #31 = { "cpu"="cortex-a8" }
|
||||
; CHECK: attributes #32 = { nounwind readnone }
|
||||
; CHECK: attributes #33 = { nounwind readonly argmemonly }
|
||||
; CHECK: attributes #34 = { nounwind argmemonly }
|
||||
; CHECK: attributes #35 = { nounwind readonly }
|
||||
; CHECK: attributes #36 = { builtin }
|
||||
; CHECK: attributes #32 = { norecurse }
|
||||
; CHECK: attributes #33 = { nounwind readnone }
|
||||
; CHECK: attributes #34 = { nounwind readonly argmemonly }
|
||||
; CHECK: attributes #35 = { nounwind argmemonly }
|
||||
; CHECK: attributes #36 = { nounwind readonly }
|
||||
; CHECK: attributes #37 = { builtin }
|
||||
|
||||
;; Metadata
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
; RUN: not llvm-dis < %s.bc 2>&1 | FileCheck %s
|
||||
|
||||
; CHECK: llvm-dis{{(\.EXE|\.exe)?}}: error: Unknown attribute kind (48)
|
||||
; CHECK: llvm-dis{{(\.EXE|\.exe)?}}: error: Unknown attribute kind (50)
|
||||
|
||||
; invalid.ll.bc has an invalid attribute number.
|
||||
; The test checks that LLVM reports the error and doesn't access freed memory
|
||||
|
Binary file not shown.
Binary file not shown.
@ -1,4 +1,4 @@
|
||||
; RUN: not llvm-lto %S/Inputs/invalid.ll.bc 2>&1 | FileCheck %s
|
||||
|
||||
|
||||
; CHECK: llvm-lto{{.*}}: error loading file '{{.*}}/Inputs/invalid.ll.bc': Unknown attribute kind (48)
|
||||
; CHECK: llvm-lto{{.*}}: error loading file '{{.*}}/Inputs/invalid.ll.bc': Unknown attribute kind (50)
|
||||
|
Loading…
x
Reference in New Issue
Block a user