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
This commit is contained in:
Nick Lewycky 2014-05-20 01:23:40 +00:00
parent 30e5830301
commit fe47ebfad3
14 changed files with 44 additions and 4 deletions

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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))

View File

@ -593,6 +593,7 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(noimplicitfloat);
KEYWORD(noinline);
KEYWORD(nonlazybind);
KEYWORD(nonnull);
KEYWORD(noredzone);
KEYWORD(noreturn);
KEYWORD(nounwind);

View File

@ -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;

View File

@ -117,6 +117,7 @@ namespace lltok {
kw_noimplicitfloat,
kw_noinline,
kw_nonlazybind,
kw_nonnull,
kw_noredzone,
kw_noreturn,
kw_nounwind,

View File

@ -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:

View File

@ -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:

View File

@ -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)

View File

@ -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 {

View File

@ -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 }