diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h index 092730242d07b7..de4fe66303246a 100644 --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -643,6 +643,7 @@ enum AttributeKindCodes { ATTR_KIND_PREALLOCATED = 65, ATTR_KIND_NO_MERGE = 66, ATTR_KIND_NULL_POINTER_IS_VALID = 67, + ATTR_KIND_NOUNDEF = 68, }; enum ComdatSelectionKindCodes { diff --git a/llvm/include/llvm/IR/Attributes.td b/llvm/include/llvm/IR/Attributes.td index 3516ce20e9889e..395f9dbfb1760a 100644 --- a/llvm/include/llvm/IR/Attributes.td +++ b/llvm/include/llvm/IR/Attributes.td @@ -39,6 +39,9 @@ def Builtin : EnumAttr<"builtin">; /// Pass structure by value. def ByVal : TypeAttr<"byval">; +/// Parameter or return value may not contain uninitialized or poison bits. +def NoUndef : EnumAttr<"noundef">; + /// Marks function as being in a cold path. def Cold : EnumAttr<"cold">; diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index 2a39e19a68b757..777ce3abdddd59 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -664,6 +664,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(noreturn); KEYWORD(nosync); KEYWORD(nocf_check); + KEYWORD(noundef); KEYWORD(nounwind); KEYWORD(null_pointer_is_valid); KEYWORD(optforfuzzing); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 85105f2c4b49e9..e3a52c7882a2f5 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -1374,6 +1374,7 @@ bool LLParser::ParseFnAttributeValuePairs(AttrBuilder &B, case lltok::kw_inalloca: case lltok::kw_nest: case lltok::kw_noalias: + case lltok::kw_noundef: case lltok::kw_nocapture: case lltok::kw_nonnull: case lltok::kw_returned: @@ -1677,6 +1678,9 @@ bool LLParser::ParseOptionalParamAttrs(AttrBuilder &B) { case lltok::kw_inalloca: B.addAttribute(Attribute::InAlloca); break; case lltok::kw_inreg: B.addAttribute(Attribute::InReg); break; case lltok::kw_nest: B.addAttribute(Attribute::Nest); break; + case lltok::kw_noundef: + B.addAttribute(Attribute::NoUndef); + break; case lltok::kw_noalias: B.addAttribute(Attribute::NoAlias); break; case lltok::kw_nocapture: B.addAttribute(Attribute::NoCapture); break; case lltok::kw_nofree: B.addAttribute(Attribute::NoFree); break; @@ -1774,6 +1778,9 @@ bool LLParser::ParseOptionalReturnAttrs(AttrBuilder &B) { } case lltok::kw_inreg: B.addAttribute(Attribute::InReg); break; case lltok::kw_noalias: B.addAttribute(Attribute::NoAlias); break; + case lltok::kw_noundef: + B.addAttribute(Attribute::NoUndef); + break; case lltok::kw_nonnull: B.addAttribute(Attribute::NonNull); break; case lltok::kw_signext: B.addAttribute(Attribute::SExt); break; case lltok::kw_zeroext: B.addAttribute(Attribute::ZExt); break; diff --git a/llvm/lib/AsmParser/LLToken.h b/llvm/lib/AsmParser/LLToken.h index 0c190bfb63b3e7..0fb3bae77dd3f2 100644 --- a/llvm/lib/AsmParser/LLToken.h +++ b/llvm/lib/AsmParser/LLToken.h @@ -196,6 +196,7 @@ enum Kind { kw_naked, kw_nest, kw_noalias, + kw_noundef, kw_nobuiltin, kw_nocapture, kw_noduplicate, diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index dceb492c912096..659e26c2bd2508 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1530,6 +1530,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) { return Attribute::SanitizeMemTag; case bitc::ATTR_KIND_PREALLOCATED: return Attribute::Preallocated; + case bitc::ATTR_KIND_NOUNDEF: + return Attribute::NoUndef; } } diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index a23f39be6b2a35..9c15a5f9f193af 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -731,6 +731,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { return bitc::ATTR_KIND_SANITIZE_MEMTAG; case Attribute::Preallocated: return bitc::ATTR_KIND_PREALLOCATED; + case Attribute::NoUndef: + return bitc::ATTR_KIND_NOUNDEF; case Attribute::EndAttrKinds: llvm_unreachable("Can not encode end-attribute kinds marker."); case Attribute::None: diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp index 4c4aa51d9e8091..f67d96a854f4d0 100644 --- a/llvm/lib/IR/Attributes.cpp +++ b/llvm/lib/IR/Attributes.cpp @@ -443,6 +443,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const { return "cold"; if (hasAttribute(Attribute::ImmArg)) return "immarg"; + if (hasAttribute(Attribute::NoUndef)) + return "noundef"; if (hasAttribute(Attribute::ByVal)) { std::string Result; diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp index 594590a746b8d9..8cdbb9d356523c 100644 --- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -877,6 +877,7 @@ Function *CodeExtractor::constructFunction(const ValueSet &inputs, case Attribute::NoMerge: case Attribute::NoReturn: case Attribute::NoSync: + case Attribute::NoUndef: case Attribute::None: case Attribute::NonNull: case Attribute::Preallocated: diff --git a/llvm/test/Bitcode/attributes.ll b/llvm/test/Bitcode/attributes.ll index 71c1fb59ebaaa5..fbbe4a80f31e0d 100644 --- a/llvm/test/Bitcode/attributes.ll +++ b/llvm/test/Bitcode/attributes.ll @@ -386,6 +386,12 @@ define void @f65() null_pointer_is_valid ret void; } +; CHECK: define noundef i32 @f66(i32 noundef %a) +define noundef i32 @f66(i32 noundef %a) +{ + ret i32 %a +} + ; CHECK: attributes #0 = { noreturn } ; CHECK: attributes #1 = { nounwind } ; CHECK: attributes #2 = { readnone }