forked from OSchip/llvm-project
[Intrinsics] Add initial support for NonNull attribute
Add initial support for NonNull attribute. (https://github.com/llvm/llvm-project/issues/57113) Test plan: verify that for __thread int x; int main() { int* y = &x; return *y; } (with this patch) clang -O -fsanitize=null -S -emit-llvm -o - doesn't emit a null-pointer check Differential revision: https://reviews.llvm.org/D131872
This commit is contained in:
parent
585f62be1a
commit
d68ba43ad2
|
@ -20,11 +20,11 @@ int g() {
|
|||
// CHECK-NEXT: %[[RET:.+]] = load i32, ptr %[[IA2]], align 4
|
||||
// CHECK-NEXT: ret i32 %[[RET]]
|
||||
//
|
||||
// CHECK: declare ptr @llvm.threadlocal.address.p0(ptr) #[[ATTR_NUM:.+]]
|
||||
// CHECK: declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull) #[[ATTR_NUM:.+]]
|
||||
//
|
||||
// CHECK-O1-LABEL: @_Z1gv
|
||||
// CHECK-O1-NEXT: entry:
|
||||
// CHECK-O1-NEXT: %[[I_ADDR:.+]] = {{.*}}call ptr @llvm.threadlocal.address.p0(ptr nonnull @i)
|
||||
// CHECK-O1-NEXT: %[[I_ADDR:.+]] = {{.*}}call ptr @llvm.threadlocal.address.p0(ptr @i)
|
||||
// CHECK-O1-NEXT: %[[VAL:.+]] = load i32, ptr %[[I_ADDR]]
|
||||
// CHECK-O1-NEXT: %[[INC:.+]] = add nsw i32 %[[VAL]], 1
|
||||
// CHECK-O1-NEXT: store i32 %[[INC]], ptr %[[I_ADDR]]
|
||||
|
@ -56,7 +56,7 @@ int f() {
|
|||
//
|
||||
// CHECK-O1-LABEL: @_Z1fv
|
||||
// CHECK-O1-NEXT: entry:
|
||||
// CHECK-O1-NEXT: %[[J_ADDR:.+]] = {{.*}}call ptr @llvm.threadlocal.address.p0(ptr nonnull @_ZZ1fvE1j)
|
||||
// CHECK-O1-NEXT: %[[J_ADDR:.+]] = {{.*}}call ptr @llvm.threadlocal.address.p0(ptr @_ZZ1fvE1j)
|
||||
// CHECK-O1-NEXT: %[[VAL:.+]] = load i32, ptr %[[J_ADDR]]
|
||||
// CHECK-O1-NEXT: %[[INC:.+]] = add nsw i32 %[[VAL]], 1
|
||||
// CHECK-O1-NEXT: store i32 %[[INC]], ptr %[[J_ADDR]]
|
||||
|
|
|
@ -84,6 +84,11 @@ class NoUndef<AttrIndex idx> : IntrinsicProperty {
|
|||
int ArgNo = idx.Value;
|
||||
}
|
||||
|
||||
// NonNull - The specified argument is not null.
|
||||
class NonNull<AttrIndex idx> : IntrinsicProperty {
|
||||
int ArgNo = idx.Value;
|
||||
}
|
||||
|
||||
class Align<AttrIndex idx, int align> : IntrinsicProperty {
|
||||
int ArgNo = idx.Value;
|
||||
int Align = align;
|
||||
|
@ -1407,7 +1412,8 @@ def int_ptrmask: DefaultAttrsIntrinsic<[llvm_anyptr_ty], [LLVMMatchType<0>, llvm
|
|||
|
||||
// Intrinsic to wrap a thread local variable.
|
||||
def int_threadlocal_address : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [LLVMMatchType<0>],
|
||||
[IntrNoMem, IntrSpeculatable, IntrWillReturn]>;
|
||||
[NonNull<RetIndex>, NonNull<ArgIndex<0>>,
|
||||
IntrNoMem, IntrSpeculatable, IntrWillReturn]>;
|
||||
|
||||
def int_experimental_stepvector : DefaultAttrsIntrinsic<[llvm_anyvector_ty],
|
||||
[], [IntrNoMem]>;
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
}
|
||||
|
||||
; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn
|
||||
declare ptr @llvm.threadlocal.address.p0(ptr) #0
|
||||
declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull) #0
|
||||
|
||||
attributes #0 = { nocallback nofree nosync nounwind readnone speculatable willreturn }
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
}
|
||||
|
||||
; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn
|
||||
declare ptr @llvm.threadlocal.address.p0(ptr) #0
|
||||
declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull) #0
|
||||
|
||||
attributes #0 = { nocallback nofree nosync nounwind readnone speculatable willreturn }
|
||||
|
||||
|
|
|
@ -37,5 +37,5 @@ entry:
|
|||
ret i32 %3
|
||||
}
|
||||
|
||||
declare ptr @llvm.threadlocal.address(ptr) nounwind readnone willreturn
|
||||
declare ptr addrspace(1) @llvm.threadlocal.address.p1(ptr addrspace(1)) nounwind readnone willreturn
|
||||
declare nonnull ptr @llvm.threadlocal.address(ptr nonnull) nounwind readnone willreturn
|
||||
declare nonnull ptr addrspace(1) @llvm.threadlocal.address.p1(ptr addrspace(1) nonnull) nounwind readnone willreturn
|
||||
|
|
|
@ -154,6 +154,7 @@ struct CodeGenIntrinsic {
|
|||
NoCapture,
|
||||
NoAlias,
|
||||
NoUndef,
|
||||
NonNull,
|
||||
Returned,
|
||||
ReadOnly,
|
||||
WriteOnly,
|
||||
|
|
|
@ -893,6 +893,9 @@ void CodeGenIntrinsic::setProperty(Record *R) {
|
|||
} else if (R->isSubClassOf("NoUndef")) {
|
||||
unsigned ArgNo = R->getValueAsInt("ArgNo");
|
||||
ArgumentAttributes.emplace_back(ArgNo, NoUndef, 0);
|
||||
} else if (R->isSubClassOf("NonNull")) {
|
||||
unsigned ArgNo = R->getValueAsInt("ArgNo");
|
||||
ArgumentAttributes.emplace_back(ArgNo, NonNull, 0);
|
||||
} else if (R->isSubClassOf("Returned")) {
|
||||
unsigned ArgNo = R->getValueAsInt("ArgNo");
|
||||
ArgumentAttributes.emplace_back(ArgNo, Returned, 0);
|
||||
|
|
|
@ -700,11 +700,13 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
|
|||
unsigned numAttrs = 0;
|
||||
|
||||
// The argument attributes are alreadys sorted by argument index.
|
||||
assert(is_sorted(Intrinsic.ArgumentAttributes) &&
|
||||
"Argument attributes are not sorted");
|
||||
|
||||
unsigned Ai = 0, Ae = Intrinsic.ArgumentAttributes.size();
|
||||
if (Ae) {
|
||||
while (Ai != Ae) {
|
||||
unsigned AttrIdx = Intrinsic.ArgumentAttributes[Ai].Index;
|
||||
|
||||
OS << " const Attribute::AttrKind AttrParam" << AttrIdx << "[]= {";
|
||||
ListSeparator LS(",");
|
||||
|
||||
|
@ -721,6 +723,9 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
|
|||
case CodeGenIntrinsic::NoUndef:
|
||||
OS << LS << "Attribute::NoUndef";
|
||||
break;
|
||||
case CodeGenIntrinsic::NonNull:
|
||||
OS << LS << "Attribute::NonNull";
|
||||
break;
|
||||
case CodeGenIntrinsic::Returned:
|
||||
OS << LS << "Attribute::Returned";
|
||||
break;
|
||||
|
@ -756,7 +761,8 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
|
|||
OS << LSV << V;
|
||||
OS << "};\n";
|
||||
}
|
||||
|
||||
// AttributeList::ReturnIndex = 0, AttrParam0 corresponds to return
|
||||
// value.
|
||||
OS << " AS[" << numAttrs++ << "] = AttributeList::get(C, "
|
||||
<< AttrIdx << ", AttrParam" << AttrIdx;
|
||||
if (!AllValuesAreZero)
|
||||
|
|
Loading…
Reference in New Issue