Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -874,6 +874,17 @@ This function attribute indicates that the function never returns with an unwind or exceptional control flow. If the function does unwind, its runtime behavior is undefined. +``optnone`` + This function attribute indicates that the function is not optimized + by any optimization or code generator passes with the + exception of interprocedural optimization passes. + This attribute cannot be used together with the ``alwaysinline`` + attribute; this attribute is also incompatible + with the ``minsize`` attribute and the ``optsize`` attribute. + + The inliner should never inline this function in any situation. + Only functions with the ``alwaysinline`` attribute are valid + candidates for inlining inside the body of this function. ``optsize`` This attribute suggests that optimization passes and code generator passes make choices that keep the code size of this function low, Index: include/llvm-c/Core.h =================================================================== --- include/llvm-c/Core.h +++ include/llvm-c/Core.h @@ -165,8 +165,9 @@ a temporary measure until the API/ABI impact to the C API is understood and the path forward agreed upon. LLVMAddressSafety = 1ULL << 32, - LLVMStackProtectStrongAttribute = 1ULL<<33 - LLVMCold = 1ULL << 34 + LLVMStackProtectStrongAttribute = 1ULL<<33, + LLVMCold = 1ULL << 34, + LLVMOptimizeNone = 1ULL << 35 */ } LLVMAttribute; Index: include/llvm/Bitcode/LLVMBitCodes.h =================================================================== --- include/llvm/Bitcode/LLVMBitCodes.h +++ include/llvm/Bitcode/LLVMBitCodes.h @@ -368,7 +368,8 @@ ATTR_KIND_UW_TABLE = 33, ATTR_KIND_Z_EXT = 34, ATTR_KIND_BUILTIN = 35, - ATTR_KIND_COLD = 36 + ATTR_KIND_COLD = 36, + ATTR_KIND_OPTIMIZE_NONE = 37 }; } // End bitc namespace Index: include/llvm/IR/Attributes.h =================================================================== --- include/llvm/IR/Attributes.h +++ include/llvm/IR/Attributes.h @@ -88,6 +88,7 @@ NoReturn, ///< Mark the function as not returning NoUnwind, ///< Function doesn't unwind stack OptimizeForSize, ///< opt_size + OptimizeNone, ///< Function must not be optimized. ReadNone, ///< Function does not access memory ReadOnly, ///< Function only reads from memory Returned, ///< Return value is always equal to this argument Index: lib/AsmParser/LLLexer.cpp =================================================================== --- lib/AsmParser/LLLexer.cpp +++ lib/AsmParser/LLLexer.cpp @@ -583,6 +583,7 @@ KEYWORD(noredzone); KEYWORD(noreturn); KEYWORD(nounwind); + KEYWORD(optnone); KEYWORD(optsize); KEYWORD(readnone); KEYWORD(readonly); Index: lib/AsmParser/LLParser.cpp =================================================================== --- lib/AsmParser/LLParser.cpp +++ lib/AsmParser/LLParser.cpp @@ -922,6 +922,7 @@ case lltok::kw_noredzone: B.addAttribute(Attribute::NoRedZone); break; case lltok::kw_noreturn: B.addAttribute(Attribute::NoReturn); 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; case lltok::kw_readnone: B.addAttribute(Attribute::ReadNone); break; case lltok::kw_readonly: B.addAttribute(Attribute::ReadOnly); break; @@ -1180,6 +1181,7 @@ case lltok::kw_noredzone: case lltok::kw_noreturn: case lltok::kw_nounwind: + case lltok::kw_optnone: case lltok::kw_optsize: case lltok::kw_returns_twice: case lltok::kw_sanitize_address: @@ -1238,6 +1240,7 @@ case lltok::kw_noredzone: case lltok::kw_noreturn: case lltok::kw_nounwind: + case lltok::kw_optnone: case lltok::kw_optsize: case lltok::kw_returns_twice: case lltok::kw_sanitize_address: Index: lib/AsmParser/LLToken.h =================================================================== --- lib/AsmParser/LLToken.h +++ lib/AsmParser/LLToken.h @@ -114,6 +114,7 @@ kw_noredzone, kw_noreturn, kw_nounwind, + kw_optnone, kw_optsize, kw_readnone, kw_readonly, Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -573,6 +573,9 @@ case bitc::ATTR_KIND_OPTIMIZE_FOR_SIZE: *Kind = Attribute::OptimizeForSize; return false; + case bitc::ATTR_KIND_OPTIMIZE_NONE: + *Kind = Attribute::OptimizeNone; + return false; case bitc::ATTR_KIND_READ_NONE: *Kind = Attribute::ReadNone; return false; Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -205,6 +205,8 @@ return bitc::ATTR_KIND_NO_UNWIND; case Attribute::OptimizeForSize: return bitc::ATTR_KIND_OPTIMIZE_FOR_SIZE; + case Attribute::OptimizeNone: + return bitc::ATTR_KIND_OPTIMIZE_NONE; case Attribute::ReadNone: return bitc::ATTR_KIND_READ_NONE; case Attribute::ReadOnly: Index: lib/IR/Attributes.cpp =================================================================== --- lib/IR/Attributes.cpp +++ lib/IR/Attributes.cpp @@ -196,6 +196,8 @@ return "noreturn"; if (hasAttribute(Attribute::NoUnwind)) return "nounwind"; + if (hasAttribute(Attribute::OptimizeNone)) + return "optnone"; if (hasAttribute(Attribute::OptimizeForSize)) return "optsize"; if (hasAttribute(Attribute::ReadNone)) @@ -381,6 +383,7 @@ case Attribute::Returned: return 1ULL << 39; case Attribute::Cold: return 1ULL << 40; case Attribute::Builtin: return 1ULL << 41; + case Attribute::OptimizeNone: return 1ULL << 42; } llvm_unreachable("Unsupported attribute type"); } Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -751,7 +751,8 @@ I->getKindAsEnum() == Attribute::NoDuplicate || I->getKindAsEnum() == Attribute::Builtin || I->getKindAsEnum() == Attribute::NoBuiltin || - I->getKindAsEnum() == Attribute::Cold) { + I->getKindAsEnum() == Attribute::Cold || + I->getKindAsEnum() == Attribute::OptimizeNone) { if (!isFunction) { CheckFailed("Attribute '" + I->getAsString() + "' only applies to functions!", V); @@ -897,6 +898,21 @@ Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::AlwaysInline)), "Attributes 'noinline and alwaysinline' are incompatible!", V); + + if (Attrs.hasAttribute(AttributeSet::FunctionIndex, + Attribute::OptimizeNone)) { + Assert1(!Attrs.hasAttribute(AttributeSet::FunctionIndex, + Attribute::AlwaysInline), + "Attributes 'alwaysinline and optnone' are incompatible!", V); + + Assert1(!Attrs.hasAttribute(AttributeSet::FunctionIndex, + Attribute::OptimizeForSize), + "Attributes 'optsize and optnone' are incompatible!", V); + + Assert1(!Attrs.hasAttribute(AttributeSet::FunctionIndex, + Attribute::MinSize), + "Attributes 'minsize and optnone' are incompatible!", V); + } } void Verifier::VerifyBitcastType(const Value *V, Type *DestTy, Type *SrcTy) { Index: lib/Target/CppBackend/CPPBackend.cpp =================================================================== --- lib/Target/CppBackend/CPPBackend.cpp +++ lib/Target/CppBackend/CPPBackend.cpp @@ -497,6 +497,7 @@ HANDLE_ATTR(ReadOnly); HANDLE_ATTR(NoInline); HANDLE_ATTR(AlwaysInline); + HANDLE_ATTR(OptimizeNone); HANDLE_ATTR(OptimizeForSize); HANDLE_ATTR(StackProtect); HANDLE_ATTR(StackProtectReq); Index: test/Bitcode/attributes.ll =================================================================== --- test/Bitcode/attributes.ll +++ test/Bitcode/attributes.ll @@ -203,10 +203,16 @@ ; CHECK: define void @f34() { call void @nobuiltin() nobuiltin -; CHECK: call void @nobuiltin() #23 +; CHECK: call void @nobuiltin() #24 ret void; } +define void @f35() optnone +; CHECK: define void @f35() #23 +{ + ret void; +} + ; CHECK: attributes #0 = { noreturn } ; CHECK: attributes #1 = { nounwind } ; CHECK: attributes #2 = { readnone } @@ -230,4 +236,6 @@ ; CHECK: attributes #20 = { "cpu"="cortex-a8" } ; CHECK: attributes #21 = { sspstrong } ; CHECK: attributes #22 = { minsize } -; CHECK: attributes #23 = { nobuiltin } +; CHECK: attributes #23 = { optnone } +; CHECK: attributes #24 = { nobuiltin } + Index: test/Feature/optnone.ll =================================================================== --- test/Feature/optnone.ll +++ test/Feature/optnone.ll @@ -0,0 +1,12 @@ +; RUN: llvm-as < %s | llvm-dis | FileCheck %s + +; Check for the presence of attribute noopt in the disassembly. + +; CHECK: @foo() #0 +define void @foo() #0 { + ret void +} + +; CHECK: attributes #0 = { optnone } +attributes #0 = { optnone } + Index: utils/kate/llvm.xml =================================================================== --- utils/kate/llvm.xml +++ utils/kate/llvm.xml @@ -85,6 +85,7 @@ noredzone noreturn nounwind + optnone optsize readnone readonly Index: utils/vim/llvm.vim =================================================================== --- utils/vim/llvm.vim +++ utils/vim/llvm.vim @@ -48,7 +48,7 @@ syn keyword llvmKeyword localdynamic localexec minsize module monotonic syn keyword llvmKeyword msp430_intrcc naked nest noalias nocapture syn keyword llvmKeyword noimplicitfloat noinline nonlazybind noredzone noreturn -syn keyword llvmKeyword nounwind optsize personality private protected +syn keyword llvmKeyword nounwind optnone optsize personality private protected syn keyword llvmKeyword ptx_device ptx_kernel readnone readonly release syn keyword llvmKeyword returns_twice sanitize_thread sanitize_memory syn keyword llvmKeyword section seq_cst sideeffect signext singlethread