diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 68ac96f9b5a8..fe23ac0ce1d0 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -879,6 +879,17 @@ example: 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, diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h index a7d17b7b8386..57834c52928f 100644 --- a/llvm/include/llvm-c/Core.h +++ b/llvm/include/llvm-c/Core.h @@ -165,8 +165,9 @@ typedef enum { 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; diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h index 463e3b919d92..90e9063d9089 100644 --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -368,7 +368,8 @@ namespace bitc { 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 diff --git a/llvm/include/llvm/IR/Attributes.h b/llvm/include/llvm/IR/Attributes.h index 2183758fbcba..ebee637004b6 100644 --- a/llvm/include/llvm/IR/Attributes.h +++ b/llvm/include/llvm/IR/Attributes.h @@ -88,6 +88,7 @@ public: 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 diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index 48675aced18e..de29c8d9a252 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -583,6 +583,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(noredzone); KEYWORD(noreturn); KEYWORD(nounwind); + KEYWORD(optnone); KEYWORD(optsize); KEYWORD(readnone); KEYWORD(readonly); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 62a07f5016a6..8fa010441a66 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -922,6 +922,7 @@ bool LLParser::ParseFnAttributeValuePairs(AttrBuilder &B, 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 @@ bool LLParser::ParseOptionalParamAttrs(AttrBuilder &B) { 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 @@ bool LLParser::ParseOptionalReturnAttrs(AttrBuilder &B) { 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: diff --git a/llvm/lib/AsmParser/LLToken.h b/llvm/lib/AsmParser/LLToken.h index 9cf4c2c42c10..9a6799d7d2c5 100644 --- a/llvm/lib/AsmParser/LLToken.h +++ b/llvm/lib/AsmParser/LLToken.h @@ -114,6 +114,7 @@ namespace lltok { kw_noredzone, kw_noreturn, kw_nounwind, + kw_optnone, kw_optsize, kw_readnone, kw_readonly, diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index e6d7b50b4898..b77c3489baf3 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -573,6 +573,9 @@ bool BitcodeReader::ParseAttrKind(uint64_t Code, Attribute::AttrKind *Kind) { 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; diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 311c233024f7..0aa919c55bef 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -205,6 +205,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { 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: diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp index f466d167e972..bcd324c4ffa4 100644 --- a/llvm/lib/IR/Attributes.cpp +++ b/llvm/lib/IR/Attributes.cpp @@ -196,6 +196,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const { 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 @@ uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) { 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"); } diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 0eda97f1289b..3d296405b187 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -751,7 +751,8 @@ void Verifier::VerifyAttributeTypes(AttributeSet Attrs, unsigned Idx, 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 @@ void Verifier::VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs, 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) { diff --git a/llvm/lib/Target/CppBackend/CPPBackend.cpp b/llvm/lib/Target/CppBackend/CPPBackend.cpp index 0ddcad2bbb86..ace4b746db2e 100644 --- a/llvm/lib/Target/CppBackend/CPPBackend.cpp +++ b/llvm/lib/Target/CppBackend/CPPBackend.cpp @@ -497,6 +497,7 @@ void CppWriter::printAttributes(const AttributeSet &PAL, HANDLE_ATTR(ReadOnly); HANDLE_ATTR(NoInline); HANDLE_ATTR(AlwaysInline); + HANDLE_ATTR(OptimizeNone); HANDLE_ATTR(OptimizeForSize); HANDLE_ATTR(StackProtect); HANDLE_ATTR(StackProtectReq); diff --git a/llvm/test/Bitcode/attributes.ll b/llvm/test/Bitcode/attributes.ll index 92f892ad1e59..2ff87d68ebcb 100644 --- a/llvm/test/Bitcode/attributes.ll +++ b/llvm/test/Bitcode/attributes.ll @@ -203,7 +203,13 @@ define void @f34() ; 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; } @@ -230,4 +236,6 @@ define void @f34() ; 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 } + diff --git a/llvm/test/Feature/optnone.ll b/llvm/test/Feature/optnone.ll new file mode 100644 index 000000000000..ec1d7232b363 --- /dev/null +++ b/llvm/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 } + diff --git a/llvm/utils/kate/llvm.xml b/llvm/utils/kate/llvm.xml index 1778cfce384e..3e32b5087162 100644 --- a/llvm/utils/kate/llvm.xml +++ b/llvm/utils/kate/llvm.xml @@ -85,6 +85,7 @@ noredzone noreturn nounwind + optnone optsize readnone readonly diff --git a/llvm/utils/vim/llvm.vim b/llvm/utils/vim/llvm.vim index 6c87cff754a4..b28c07faacb7 100644 --- a/llvm/utils/vim/llvm.vim +++ b/llvm/utils/vim/llvm.vim @@ -48,7 +48,7 @@ syn keyword llvmKeyword linkonce linkonce_odr linkonce_odr_auto_hide 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