forked from OSchip/llvm-project
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!
llvm-svn: 209185
This commit is contained in:
parent
57cccec446
commit
d52b1528c0
|
@ -847,6 +847,13 @@ Currently, only the following parameter attributes are defined:
|
||||||
operands for the :ref:`bitcast instruction <i_bitcast>`. This is not a
|
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.
|
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:
|
.. _gc:
|
||||||
|
|
||||||
Garbage Collector Names
|
Garbage Collector Names
|
||||||
|
|
|
@ -165,7 +165,8 @@ typedef enum {
|
||||||
LLVMStackProtectStrongAttribute = 1ULL<<33,
|
LLVMStackProtectStrongAttribute = 1ULL<<33,
|
||||||
LLVMCold = 1ULL << 34,
|
LLVMCold = 1ULL << 34,
|
||||||
LLVMOptimizeNone = 1ULL << 35,
|
LLVMOptimizeNone = 1ULL << 35,
|
||||||
LLVMInAllocaAttribute = 1ULL << 36
|
LLVMInAllocaAttribute = 1ULL << 36,
|
||||||
|
LLVMNonNullAttribute = 1ULL << 37
|
||||||
*/
|
*/
|
||||||
} LLVMAttribute;
|
} LLVMAttribute;
|
||||||
|
|
||||||
|
|
|
@ -371,7 +371,8 @@ namespace bitc {
|
||||||
ATTR_KIND_BUILTIN = 35,
|
ATTR_KIND_BUILTIN = 35,
|
||||||
ATTR_KIND_COLD = 36,
|
ATTR_KIND_COLD = 36,
|
||||||
ATTR_KIND_OPTIMIZE_NONE = 37,
|
ATTR_KIND_OPTIMIZE_NONE = 37,
|
||||||
ATTR_KIND_IN_ALLOCA = 38
|
ATTR_KIND_IN_ALLOCA = 38,
|
||||||
|
ATTR_KIND_NON_NULL = 39
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End bitc namespace
|
} // End bitc namespace
|
||||||
|
|
|
@ -55,6 +55,10 @@ public:
|
||||||
/// For example in "void foo(int a, float b)" a is 0 and b is 1.
|
/// For example in "void foo(int a, float b)" a is 0 and b is 1.
|
||||||
unsigned getArgNo() const;
|
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
|
/// \brief Return true if this argument has the byval attribute on it in its
|
||||||
/// containing function.
|
/// containing function.
|
||||||
bool hasByValAttr() const;
|
bool hasByValAttr() const;
|
||||||
|
|
|
@ -86,6 +86,7 @@ public:
|
||||||
NoInline, ///< inline=never
|
NoInline, ///< inline=never
|
||||||
NonLazyBind, ///< Function is called early and/or
|
NonLazyBind, ///< Function is called early and/or
|
||||||
///< often, so lazy binding isn't worthwhile
|
///< often, so lazy binding isn't worthwhile
|
||||||
|
NonNull, ///< Pointer is known to be not null
|
||||||
NoRedZone, ///< Disable redzone
|
NoRedZone, ///< Disable redzone
|
||||||
NoReturn, ///< Mark the function as not returning
|
NoReturn, ///< Mark the function as not returning
|
||||||
NoUnwind, ///< Function doesn't unwind stack
|
NoUnwind, ///< Function doesn't unwind stack
|
||||||
|
|
|
@ -2065,9 +2065,9 @@ bool llvm::isKnownNonNull(const Value *V, const TargetLibraryInfo *TLI) {
|
||||||
// Alloca never returns null, malloc might.
|
// Alloca never returns null, malloc might.
|
||||||
if (isa<AllocaInst>(V)) return true;
|
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))
|
if (const Argument *A = dyn_cast<Argument>(V))
|
||||||
return A->hasByValOrInAllocaAttr();
|
return A->hasByValOrInAllocaAttr() || A->hasNonNullAttr();
|
||||||
|
|
||||||
// Global values are not null unless extern weak.
|
// Global values are not null unless extern weak.
|
||||||
if (const GlobalValue *GV = dyn_cast<GlobalValue>(V))
|
if (const GlobalValue *GV = dyn_cast<GlobalValue>(V))
|
||||||
|
|
|
@ -593,6 +593,7 @@ lltok::Kind LLLexer::LexIdentifier() {
|
||||||
KEYWORD(noimplicitfloat);
|
KEYWORD(noimplicitfloat);
|
||||||
KEYWORD(noinline);
|
KEYWORD(noinline);
|
||||||
KEYWORD(nonlazybind);
|
KEYWORD(nonlazybind);
|
||||||
|
KEYWORD(nonnull);
|
||||||
KEYWORD(noredzone);
|
KEYWORD(noredzone);
|
||||||
KEYWORD(noreturn);
|
KEYWORD(noreturn);
|
||||||
KEYWORD(nounwind);
|
KEYWORD(nounwind);
|
||||||
|
|
|
@ -1003,6 +1003,7 @@ bool LLParser::ParseFnAttributeValuePairs(AttrBuilder &B,
|
||||||
case lltok::kw_nest:
|
case lltok::kw_nest:
|
||||||
case lltok::kw_noalias:
|
case lltok::kw_noalias:
|
||||||
case lltok::kw_nocapture:
|
case lltok::kw_nocapture:
|
||||||
|
case lltok::kw_nonnull:
|
||||||
case lltok::kw_returned:
|
case lltok::kw_returned:
|
||||||
case lltok::kw_sret:
|
case lltok::kw_sret:
|
||||||
HaveError |=
|
HaveError |=
|
||||||
|
@ -1217,6 +1218,7 @@ bool LLParser::ParseOptionalParamAttrs(AttrBuilder &B) {
|
||||||
case lltok::kw_nest: B.addAttribute(Attribute::Nest); break;
|
case lltok::kw_nest: B.addAttribute(Attribute::Nest); break;
|
||||||
case lltok::kw_noalias: B.addAttribute(Attribute::NoAlias); break;
|
case lltok::kw_noalias: B.addAttribute(Attribute::NoAlias); break;
|
||||||
case lltok::kw_nocapture: B.addAttribute(Attribute::NoCapture); 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_readnone: B.addAttribute(Attribute::ReadNone); break;
|
||||||
case lltok::kw_readonly: B.addAttribute(Attribute::ReadOnly); break;
|
case lltok::kw_readonly: B.addAttribute(Attribute::ReadOnly); break;
|
||||||
case lltok::kw_returned: B.addAttribute(Attribute::Returned); break;
|
case lltok::kw_returned: B.addAttribute(Attribute::Returned); break;
|
||||||
|
@ -1269,6 +1271,7 @@ bool LLParser::ParseOptionalReturnAttrs(AttrBuilder &B) {
|
||||||
return HaveError;
|
return HaveError;
|
||||||
case lltok::kw_inreg: B.addAttribute(Attribute::InReg); break;
|
case lltok::kw_inreg: B.addAttribute(Attribute::InReg); break;
|
||||||
case lltok::kw_noalias: B.addAttribute(Attribute::NoAlias); 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_signext: B.addAttribute(Attribute::SExt); break;
|
||||||
case lltok::kw_zeroext: B.addAttribute(Attribute::ZExt); break;
|
case lltok::kw_zeroext: B.addAttribute(Attribute::ZExt); break;
|
||||||
|
|
||||||
|
|
|
@ -117,6 +117,7 @@ namespace lltok {
|
||||||
kw_noimplicitfloat,
|
kw_noimplicitfloat,
|
||||||
kw_noinline,
|
kw_noinline,
|
||||||
kw_nonlazybind,
|
kw_nonlazybind,
|
||||||
|
kw_nonnull,
|
||||||
kw_noredzone,
|
kw_noredzone,
|
||||||
kw_noreturn,
|
kw_noreturn,
|
||||||
kw_nounwind,
|
kw_nounwind,
|
||||||
|
|
|
@ -569,6 +569,8 @@ static Attribute::AttrKind GetAttrFromCode(uint64_t Code) {
|
||||||
return Attribute::NoInline;
|
return Attribute::NoInline;
|
||||||
case bitc::ATTR_KIND_NON_LAZY_BIND:
|
case bitc::ATTR_KIND_NON_LAZY_BIND:
|
||||||
return Attribute::NonLazyBind;
|
return Attribute::NonLazyBind;
|
||||||
|
case bitc::ATTR_KIND_NON_NULL:
|
||||||
|
return Attribute::NonNull;
|
||||||
case bitc::ATTR_KIND_NO_RED_ZONE:
|
case bitc::ATTR_KIND_NO_RED_ZONE:
|
||||||
return Attribute::NoRedZone;
|
return Attribute::NoRedZone;
|
||||||
case bitc::ATTR_KIND_NO_RETURN:
|
case bitc::ATTR_KIND_NO_RETURN:
|
||||||
|
|
|
@ -197,6 +197,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) {
|
||||||
return bitc::ATTR_KIND_NO_INLINE;
|
return bitc::ATTR_KIND_NO_INLINE;
|
||||||
case Attribute::NonLazyBind:
|
case Attribute::NonLazyBind:
|
||||||
return bitc::ATTR_KIND_NON_LAZY_BIND;
|
return bitc::ATTR_KIND_NON_LAZY_BIND;
|
||||||
|
case Attribute::NonNull:
|
||||||
|
return bitc::ATTR_KIND_NON_NULL;
|
||||||
case Attribute::NoRedZone:
|
case Attribute::NoRedZone:
|
||||||
return bitc::ATTR_KIND_NO_RED_ZONE;
|
return bitc::ATTR_KIND_NO_RED_ZONE;
|
||||||
case Attribute::NoReturn:
|
case Attribute::NoReturn:
|
||||||
|
|
|
@ -193,6 +193,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
|
||||||
return "noinline";
|
return "noinline";
|
||||||
if (hasAttribute(Attribute::NonLazyBind))
|
if (hasAttribute(Attribute::NonLazyBind))
|
||||||
return "nonlazybind";
|
return "nonlazybind";
|
||||||
|
if (hasAttribute(Attribute::NonNull))
|
||||||
|
return "nonnull";
|
||||||
if (hasAttribute(Attribute::NoRedZone))
|
if (hasAttribute(Attribute::NoRedZone))
|
||||||
return "noredzone";
|
return "noredzone";
|
||||||
if (hasAttribute(Attribute::NoReturn))
|
if (hasAttribute(Attribute::NoReturn))
|
||||||
|
@ -392,6 +394,7 @@ uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) {
|
||||||
case Attribute::Builtin: return 1ULL << 41;
|
case Attribute::Builtin: return 1ULL << 41;
|
||||||
case Attribute::OptimizeNone: return 1ULL << 42;
|
case Attribute::OptimizeNone: return 1ULL << 42;
|
||||||
case Attribute::InAlloca: return 1ULL << 43;
|
case Attribute::InAlloca: return 1ULL << 43;
|
||||||
|
case Attribute::NonNull: return 1ULL << 44;
|
||||||
}
|
}
|
||||||
llvm_unreachable("Unsupported attribute type");
|
llvm_unreachable("Unsupported attribute type");
|
||||||
}
|
}
|
||||||
|
@ -1177,6 +1180,7 @@ AttributeSet AttributeFuncs::typeIncompatible(Type *Ty, uint64_t Index) {
|
||||||
.addAttribute(Attribute::Nest)
|
.addAttribute(Attribute::Nest)
|
||||||
.addAttribute(Attribute::NoAlias)
|
.addAttribute(Attribute::NoAlias)
|
||||||
.addAttribute(Attribute::NoCapture)
|
.addAttribute(Attribute::NoCapture)
|
||||||
|
.addAttribute(Attribute::NonNull)
|
||||||
.addAttribute(Attribute::ReadNone)
|
.addAttribute(Attribute::ReadNone)
|
||||||
.addAttribute(Attribute::ReadOnly)
|
.addAttribute(Attribute::ReadOnly)
|
||||||
.addAttribute(Attribute::StructRet)
|
.addAttribute(Attribute::StructRet)
|
||||||
|
|
|
@ -76,6 +76,14 @@ unsigned Argument::getArgNo() const {
|
||||||
return ArgIdx;
|
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
|
/// hasByValAttr - Return true if this argument has the byval attribute on it
|
||||||
/// in its containing function.
|
/// in its containing function.
|
||||||
bool Argument::hasByValAttr() const {
|
bool Argument::hasByValAttr() const {
|
||||||
|
|
|
@ -218,6 +218,11 @@ define void @f36(i8* inalloca) {
|
||||||
ret void
|
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 #0 = { noreturn }
|
||||||
; CHECK: attributes #1 = { nounwind }
|
; CHECK: attributes #1 = { nounwind }
|
||||||
; CHECK: attributes #2 = { readnone }
|
; CHECK: attributes #2 = { readnone }
|
||||||
|
|
Loading…
Reference in New Issue