diff options
author | Nick Lewycky <nicholas@mxc.ca> | 2014-05-20 01:23:40 +0000 |
---|---|---|
committer | Nick Lewycky <nicholas@mxc.ca> | 2014-05-20 01:23:40 +0000 |
commit | fe47ebfad39184dfca0733c5ef943a074bfcc187 (patch) | |
tree | 2f60176fb1f04022ea8a167ff280bc824f18f11a | |
parent | 30e58303015fe880180e3caffdd8a3264cde236a (diff) | |
download | llvm-fe47ebfad39184dfca0733c5ef943a074bfcc187.tar.gz llvm-fe47ebfad39184dfca0733c5ef943a074bfcc187.tar.bz2 llvm-fe47ebfad39184dfca0733c5ef943a074bfcc187.tar.xz |
Add 'nonnull', a new parameter and return attribute which indicates that the pointer is not null. Instcombine will elide comparisons between these and null. Patch by Luqman Aden!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@209185 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | docs/LangRef.rst | 7 | ||||
-rw-r--r-- | include/llvm-c/Core.h | 3 | ||||
-rw-r--r-- | include/llvm/Bitcode/LLVMBitCodes.h | 3 | ||||
-rw-r--r-- | include/llvm/IR/Argument.h | 4 | ||||
-rw-r--r-- | include/llvm/IR/Attributes.h | 1 | ||||
-rw-r--r-- | lib/Analysis/ValueTracking.cpp | 4 | ||||
-rw-r--r-- | lib/AsmParser/LLLexer.cpp | 1 | ||||
-rw-r--r-- | lib/AsmParser/LLParser.cpp | 3 | ||||
-rw-r--r-- | lib/AsmParser/LLToken.h | 1 | ||||
-rw-r--r-- | lib/Bitcode/Reader/BitcodeReader.cpp | 2 | ||||
-rw-r--r-- | lib/Bitcode/Writer/BitcodeWriter.cpp | 2 | ||||
-rw-r--r-- | lib/IR/Attributes.cpp | 4 | ||||
-rw-r--r-- | lib/IR/Function.cpp | 8 | ||||
-rw-r--r-- | test/Bitcode/attributes.ll | 5 |
14 files changed, 44 insertions, 4 deletions
diff --git a/docs/LangRef.rst b/docs/LangRef.rst index d2f9a1d4f1..ceec1bd547 100644 --- a/docs/LangRef.rst +++ b/docs/LangRef.rst @@ -847,6 +847,13 @@ Currently, only the following parameter attributes are defined: operands for the :ref:`bitcast instruction <i_bitcast>`. This is not a valid attribute for return values and can only be applied to one parameter. +``nonnull`` + This indicates that the parameter or return pointer is not null. This + attribute may only be applied to pointer typed parameters. This is not + checked or enforced by LLVM, the caller must ensure that the pointer + passed in is non-null, or the callee must ensure that the returned pointer + is non-null. + .. _gc: Garbage Collector Names diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index 151165e704..f37e3f89ca 100644 --- a/include/llvm-c/Core.h +++ b/include/llvm-c/Core.h @@ -165,7 +165,8 @@ typedef enum { LLVMStackProtectStrongAttribute = 1ULL<<33, LLVMCold = 1ULL << 34, LLVMOptimizeNone = 1ULL << 35, - LLVMInAllocaAttribute = 1ULL << 36 + LLVMInAllocaAttribute = 1ULL << 36, + LLVMNonNullAttribute = 1ULL << 37 */ } LLVMAttribute; diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index a07dc585b8..04c08ab3f4 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -371,7 +371,8 @@ namespace bitc { ATTR_KIND_BUILTIN = 35, ATTR_KIND_COLD = 36, ATTR_KIND_OPTIMIZE_NONE = 37, - ATTR_KIND_IN_ALLOCA = 38 + ATTR_KIND_IN_ALLOCA = 38, + ATTR_KIND_NON_NULL = 39 }; } // End bitc namespace diff --git a/include/llvm/IR/Argument.h b/include/llvm/IR/Argument.h index d226bd3c85..3a63e1a1ea 100644 --- a/include/llvm/IR/Argument.h +++ b/include/llvm/IR/Argument.h @@ -55,6 +55,10 @@ public: /// For example in "void foo(int a, float b)" a is 0 and b is 1. unsigned getArgNo() const; + /// \brief Return true if this argument has the nonnull attribute on it in + /// its containing function. + bool hasNonNullAttr() const; + /// \brief Return true if this argument has the byval attribute on it in its /// containing function. bool hasByValAttr() const; diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h index cb4275337d..86f9cc8894 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -86,6 +86,7 @@ public: NoInline, ///< inline=never NonLazyBind, ///< Function is called early and/or ///< often, so lazy binding isn't worthwhile + NonNull, ///< Pointer is known to be not null NoRedZone, ///< Disable redzone NoReturn, ///< Mark the function as not returning NoUnwind, ///< Function doesn't unwind stack diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index 44305bb016..280f15b509 100644 --- a/lib/Analysis/ValueTracking.cpp +++ b/lib/Analysis/ValueTracking.cpp @@ -2065,9 +2065,9 @@ bool llvm::isKnownNonNull(const Value *V, const TargetLibraryInfo *TLI) { // Alloca never returns null, malloc might. if (isa<AllocaInst>(V)) return true; - // A byval or inalloca argument is never null. + // A byval, inalloca, or nonnull argument is never null. if (const Argument *A = dyn_cast<Argument>(V)) - return A->hasByValOrInAllocaAttr(); + return A->hasByValOrInAllocaAttr() || A->hasNonNullAttr(); // Global values are not null unless extern weak. if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index 905bc20bc5..44a34126e4 100644 --- a/lib/AsmParser/LLLexer.cpp +++ b/lib/AsmParser/LLLexer.cpp @@ -593,6 +593,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(noimplicitfloat); KEYWORD(noinline); KEYWORD(nonlazybind); + KEYWORD(nonnull); KEYWORD(noredzone); KEYWORD(noreturn); KEYWORD(nounwind); diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 4c020c1bfc..3282e8a23b 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -1003,6 +1003,7 @@ bool LLParser::ParseFnAttributeValuePairs(AttrBuilder &B, case lltok::kw_nest: case lltok::kw_noalias: case lltok::kw_nocapture: + case lltok::kw_nonnull: case lltok::kw_returned: case lltok::kw_sret: HaveError |= @@ -1217,6 +1218,7 @@ bool LLParser::ParseOptionalParamAttrs(AttrBuilder &B) { case lltok::kw_nest: B.addAttribute(Attribute::Nest); break; case lltok::kw_noalias: B.addAttribute(Attribute::NoAlias); break; case lltok::kw_nocapture: B.addAttribute(Attribute::NoCapture); break; + case lltok::kw_nonnull: B.addAttribute(Attribute::NonNull); break; case lltok::kw_readnone: B.addAttribute(Attribute::ReadNone); break; case lltok::kw_readonly: B.addAttribute(Attribute::ReadOnly); break; case lltok::kw_returned: B.addAttribute(Attribute::Returned); break; @@ -1269,6 +1271,7 @@ bool LLParser::ParseOptionalReturnAttrs(AttrBuilder &B) { return HaveError; case lltok::kw_inreg: B.addAttribute(Attribute::InReg); break; case lltok::kw_noalias: B.addAttribute(Attribute::NoAlias); 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/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h index d5d45312c2..b6b7d824b5 100644 --- a/lib/AsmParser/LLToken.h +++ b/lib/AsmParser/LLToken.h @@ -117,6 +117,7 @@ namespace lltok { kw_noimplicitfloat, kw_noinline, kw_nonlazybind, + kw_nonnull, kw_noredzone, kw_noreturn, kw_nounwind, diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index fe5d57262e..4170f98567 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -569,6 +569,8 @@ static Attribute::AttrKind GetAttrFromCode(uint64_t Code) { return Attribute::NoInline; case bitc::ATTR_KIND_NON_LAZY_BIND: return Attribute::NonLazyBind; + case bitc::ATTR_KIND_NON_NULL: + return Attribute::NonNull; case bitc::ATTR_KIND_NO_RED_ZONE: return Attribute::NoRedZone; case bitc::ATTR_KIND_NO_RETURN: diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index 23374872df..db254e6a94 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -197,6 +197,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { return bitc::ATTR_KIND_NO_INLINE; case Attribute::NonLazyBind: return bitc::ATTR_KIND_NON_LAZY_BIND; + case Attribute::NonNull: + return bitc::ATTR_KIND_NON_NULL; case Attribute::NoRedZone: return bitc::ATTR_KIND_NO_RED_ZONE; case Attribute::NoReturn: diff --git a/lib/IR/Attributes.cpp b/lib/IR/Attributes.cpp index 0bbbd55978..a9074bb294 100644 --- a/lib/IR/Attributes.cpp +++ b/lib/IR/Attributes.cpp @@ -193,6 +193,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const { return "noinline"; if (hasAttribute(Attribute::NonLazyBind)) return "nonlazybind"; + if (hasAttribute(Attribute::NonNull)) + return "nonnull"; if (hasAttribute(Attribute::NoRedZone)) return "noredzone"; if (hasAttribute(Attribute::NoReturn)) @@ -392,6 +394,7 @@ uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) { case Attribute::Builtin: return 1ULL << 41; case Attribute::OptimizeNone: return 1ULL << 42; case Attribute::InAlloca: return 1ULL << 43; + case Attribute::NonNull: return 1ULL << 44; } llvm_unreachable("Unsupported attribute type"); } @@ -1177,6 +1180,7 @@ AttributeSet AttributeFuncs::typeIncompatible(Type *Ty, uint64_t Index) { .addAttribute(Attribute::Nest) .addAttribute(Attribute::NoAlias) .addAttribute(Attribute::NoCapture) + .addAttribute(Attribute::NonNull) .addAttribute(Attribute::ReadNone) .addAttribute(Attribute::ReadOnly) .addAttribute(Attribute::StructRet) diff --git a/lib/IR/Function.cpp b/lib/IR/Function.cpp index de8e66f1bc..fe32c4613e 100644 --- a/lib/IR/Function.cpp +++ b/lib/IR/Function.cpp @@ -76,6 +76,14 @@ unsigned Argument::getArgNo() const { return ArgIdx; } +/// hasNonNullAttr - Return true if this argument has the nonnull attribute on +/// it in its containing function. +bool Argument::hasNonNullAttr() const { + if (!getType()->isPointerTy()) return false; + return getParent()->getAttributes(). + hasAttribute(getArgNo()+1, Attribute::NonNull); +} + /// hasByValAttr - Return true if this argument has the byval attribute on it /// in its containing function. bool Argument::hasByValAttr() const { diff --git a/test/Bitcode/attributes.ll b/test/Bitcode/attributes.ll index 545f1cbb28..02e1bb1c4e 100644 --- a/test/Bitcode/attributes.ll +++ b/test/Bitcode/attributes.ll @@ -218,6 +218,11 @@ define void @f36(i8* inalloca) { ret void } +define nonnull i8* @f37(i8* nonnull %a) { +; CHECK: define nonnull i8* @f37(i8* nonnull %a) { + ret i8* %a +} + ; CHECK: attributes #0 = { noreturn } ; CHECK: attributes #1 = { nounwind } ; CHECK: attributes #2 = { readnone } |