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