From bb3f169b59e1c8bd7fd70097532220bbd11e9967 Mon Sep 17 00:00:00 2001 From: =?utf8?q?D=C3=A1vid=20Bolvansk=C3=BD?= Date: Thu, 21 Jan 2021 00:12:28 +0100 Subject: [PATCH] [BuildLibcalls, Attrs] Support more variants of C++'s new, add attributes for C++'s delete Reviewed By: jdoerfert Differential Revision: https://reviews.llvm.org/D95095 --- llvm/lib/Transforms/Utils/BuildLibCalls.cpp | 42 ++++++++++++++++++++++ .../test/Transforms/InferFunctionAttrs/annotate.ll | 36 ++++++++++++++++--- 2 files changed, 73 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp index 857c3d915e8..a14c3007139 100644 --- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp @@ -1001,10 +1001,52 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) { Changed |= setDoesNotCapture(F, 0); Changed |= setDoesNotCapture(F, 1); return Changed; + case LibFunc_ZdlPvRKSt9nothrow_t: // delete(void*, nothrow) + case LibFunc_ZdlPvSt11align_val_tRKSt9nothrow_t: // delete(void*, align_val_t, nothrow) + case LibFunc_ZdaPvRKSt9nothrow_t: // delete[](void*, nothrow) + case LibFunc_ZdaPvSt11align_val_tRKSt9nothrow_t: // delete[](void*, align_val_t, nothrow) + Changed |= setDoesNotThrow(F); + LLVM_FALLTHROUGH; + case LibFunc_ZdlPv: // delete(void*) + case LibFunc_ZdlPvj: // delete(void*, unsigned int) + case LibFunc_ZdlPvm: // delete(void*, unsigned long) + case LibFunc_ZdaPv: // delete[](void*) + case LibFunc_ZdaPvj: // delete[](void*, unsigned int) + case LibFunc_ZdaPvm: // delete[](void*, unsigned long) + case LibFunc_ZdlPvSt11align_val_t: // delete(void*, align_val_t) + case LibFunc_ZdlPvjSt11align_val_t: // delete(void*, unsigned int, align_val_t) + case LibFunc_ZdlPvmSt11align_val_t: // delete(void*, unsigned long, align_val_t) + case LibFunc_ZdaPvSt11align_val_t: // delete[](void*, align_val_t) + case LibFunc_ZdaPvjSt11align_val_t: // delete[](void*, unsigned int, align_val_t) + case LibFunc_ZdaPvmSt11align_val_t: // delete[](void*, unsigned long, align_val_t); + Changed |= setOnlyAccessesInaccessibleMemOrArgMem(F); + Changed |= setArgsNoUndef(F); + Changed |= setWillReturn(F); + Changed |= setDoesNotCapture(F, 0); + return Changed; + case LibFunc_ZnwjRKSt9nothrow_t: // new(unsigned int, nothrow) + case LibFunc_ZnwmRKSt9nothrow_t: // new(unsigned long, nothrow) + case LibFunc_ZnajRKSt9nothrow_t: // new[](unsigned int, nothrow) + case LibFunc_ZnamRKSt9nothrow_t: // new[](unsigned long, nothrow) + case LibFunc_ZnwjSt11align_val_tRKSt9nothrow_t: // new(unsigned int, align_val_t, nothrow) + case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t: // new(unsigned long, align_val_t, nothrow) + case LibFunc_ZnajSt11align_val_tRKSt9nothrow_t: // new[](unsigned int, align_val_t, nothrow) + case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t: // new[](unsigned long, align_val_t, nothrow) + // Nothrow operator new may return null pointer + Changed |= setDoesNotThrow(F); + Changed |= setOnlyAccessesInaccessibleMemory(F); + Changed |= setRetNoUndef(F); + Changed |= setRetDoesNotAlias(F); + Changed |= setWillReturn(F); + return Changed; case LibFunc_Znwj: // new(unsigned int) case LibFunc_Znwm: // new(unsigned long) case LibFunc_Znaj: // new[](unsigned int) case LibFunc_Znam: // new[](unsigned long) + case LibFunc_ZnwjSt11align_val_t: // new(unsigned int, align_val_t) + case LibFunc_ZnwmSt11align_val_t: // new(unsigned long, align_val_t) + case LibFunc_ZnajSt11align_val_t: // new[](unsigned int, align_val_t) + case LibFunc_ZnamSt11align_val_t: // new[](unsigned long, align_val_t) case LibFunc_msvc_new_int: // new(unsigned int) case LibFunc_msvc_new_longlong: // new(unsigned long long) case LibFunc_msvc_new_array_int: // new[](unsigned int) diff --git a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll index 0af18151d6f..a847db7eb55 100644 --- a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll +++ b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll @@ -9,6 +9,30 @@ declare i8* @_Znwj(i64 ) ; CHECK: declare noalias noundef nonnull i8* @_Znwj(i64) [[INACCESSIBLEMEMONLY_NOFREE_WILLRETURN:#[0-9]+]] declare i8* @_Znwm(i64) ; CHECK: declare noalias noundef nonnull i8* @_Znwm(i64) [[INACCESSIBLEMEMONLY_NOFREE_WILLRETURN]] +declare i8* @_Znaj(i64) +; CHECK: declare noalias noundef nonnull i8* @_Znaj(i64) [[INACCESSIBLEMEMONLY_NOFREE_WILLRETURN]] +declare i8* @_Znam(i64) +; CHECK: declare noalias noundef nonnull i8* @_Znam(i64) [[INACCESSIBLEMEMONLY_NOFREE_WILLRETURN]] + + +%"struct.std::nothrow_t" = type { i8 } +declare i8* @_ZnwmRKSt9nothrow_t(i64, %"struct.std::nothrow_t"*) +; CHECK: declare noalias noundef i8* @_ZnwmRKSt9nothrow_t(i64, %"struct.std::nothrow_t"*) [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] + + +; operator delete routines +declare void @_ZdlPv(i8*) +; CHECK: declare void @_ZdlPv(i8* nocapture noundef) [[INACCESSIBLEMEMORARGONLY_WILLRETURN:#[0-9]+]] +declare void @_ZdlPvj(i8*, i64) +; CHECK: declare void @_ZdlPvj(i8* nocapture noundef, i64 noundef) [[INACCESSIBLEMEMORARGONLY_WILLRETURN]] +declare void @_ZdlPvm(i8*, i64) +; CHECK: declare void @_ZdlPvm(i8* nocapture noundef, i64 noundef) [[INACCESSIBLEMEMORARGONLY_WILLRETURN]] +declare void @_ZdaPv(i8*) +; CHECK: declare void @_ZdaPv(i8* nocapture noundef) [[INACCESSIBLEMEMORARGONLY_WILLRETURN]] +declare void @_ZdaPvj(i8*, i64) +; CHECK: declare void @_ZdaPvj(i8* nocapture noundef, i64 noundef) [[INACCESSIBLEMEMORARGONLY_WILLRETURN]] +declare void @_ZdaPvm(i8*, i64) +; CHECK: declare void @_ZdaPvm(i8* nocapture noundef, i64 noundef) [[INACCESSIBLEMEMORARGONLY_WILLRETURN]] declare i32 @__nvvm_reflect(i8*) ; CHECK-NVPTX: declare noundef i32 @__nvvm_reflect(i8* noundef) [[NOFREE_NOUNWIND_READNONE:#[0-9]+]] @@ -256,7 +280,7 @@ declare void @bcopy(i8*, i8*, i64) ; CHECK: declare void @bzero(i8* nocapture writeonly, i64) [[ARGMEMONLY_NOFREE_NOUNWIND:#[0-9]+]] declare void @bzero(i8*, i64) -; CHECK: declare noalias noundef i8* @calloc(i64, i64) [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] +; CHECK: declare noalias noundef i8* @calloc(i64, i64) [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN]] declare i8* @calloc(i64, i64) ; CHECK: declare double @cbrt(double) [[NOFREE_NOUNWIND_WILLRETURN]] @@ -454,7 +478,7 @@ declare i32 @fputs(i8*, %opaque*) ; CHECK: declare noundef i64 @fread(i8* nocapture noundef, i64 noundef, i64 noundef, %opaque* nocapture noundef) [[NOFREE_NOUNWIND]] declare i64 @fread(i8*, i64, i64, %opaque*) -; CHECK: declare void @free(i8* nocapture noundef) [[NOUNWIND:#[0-9]+]] +; CHECK: declare void @free(i8* nocapture noundef) [[INACCESSIBLEMEMORARGONLY_NOUNWIND_WILLRETURN:#[0-9]+]] declare void @free(i8*) ; CHECK: declare double @frexp(double, i32* nocapture) [[NOFREE_NOUNWIND_WILLRETURN]] @@ -733,7 +757,7 @@ declare i64 @read(i32, i8*, i64) ; CHECK: declare noundef i64 @readlink(i8* nocapture noundef readonly, i8* nocapture noundef, i64 noundef) [[NOFREE_NOUNWIND]] declare i64 @readlink(i8*, i8*, i64) -; CHECK: declare noalias noundef i8* @realloc(i8* nocapture, i64) [[NOUNWIND]] +; CHECK: declare noalias noundef i8* @realloc(i8* nocapture, i64) [[INACCESSIBLEMEMORARGONLY_NOUNWIND_WILLRETURN]] declare i8* @realloc(i8*, i64) ; CHECK: declare noundef i8* @reallocf(i8*, i64) @@ -1018,9 +1042,10 @@ declare i64 @write(i32, i8*, i64) declare void @memset_pattern16(i8*, i8*, i64) ; CHECK-DAG-UNKNOWN: attributes [[INACCESSIBLEMEMONLY_NOFREE_WILLRETURN]] = { inaccessiblememonly nofree willreturn } +; CHECK-DAG-UNKNOWN: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN]] = { inaccessiblememonly nofree nounwind willreturn } +; CHECK-DAG-UNKNOWN: attributes [[INACCESSIBLEMEMORARGONLY_WILLRETURN]] = { inaccessiblemem_or_argmemonly willreturn } ; CHECK-DAG-UNKNOWN: attributes [[NOFREE_NOUNWIND_WILLRETURN]] = { nofree nounwind willreturn } ; CHECK-DAG-UNKNOWN: attributes [[NOFREE_NOUNWIND]] = { nofree nounwind } -; CHECK-DAG-UNKNOWN: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN]] = { inaccessiblememonly nofree nounwind willreturn } ; CHECK-DAG-UNKNOWN: attributes [[NOFREE_NOUNWIND_READONLY_WILLRETURN]] = { nofree nounwind readonly willreturn } ; CHECK-DAG-UNKNOWN: attributes [[NOFREE_NOUNWIND_READONLY_WILLRETURN]] = { argmemonly nofree nounwind willreturn } ; CHECK-DAG-UNKNOWN: attributes [[NOFREE_NOUNWIND_READONLY]] = { nofree nounwind readonly } @@ -1032,10 +1057,11 @@ declare void @memset_pattern16(i8*, i8*, i64) ; CHECK-DAG-UNKNOWN: attributes [[INACCESSIBLEMEMORARGONLY_NOFREE_NOUNWIND_WILLRETURN]] = { inaccessiblemem_or_argmemonly nofree nounwind willreturn } ; CHECK-DAG-LINUX: attributes [[INACCESSIBLEMEMONLY_NOFREE_WILLRETURN]] = { inaccessiblememonly nofree willreturn } +; CHECK-DAG-LINUX: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN]] = { inaccessiblememonly nofree nounwind willreturn } +; CHECK-DAG-LINUX: attributes [[INACCESSIBLEMEMORARGONLY_WILLRETURN]] = { inaccessiblemem_or_argmemonly willreturn } ; CHECK-DAG-LINUX: attributes [[NOFREE]] = { nofree } ; CHECK-DAG-LINUX: attributes [[NOFREE_NOUNWIND_WILLRETURN]] = { nofree nounwind willreturn } ; CHECK-DAG-LINUX: attributes [[NOFREE_NOUNWIND]] = { nofree nounwind } -; CHECK-DAG-LINUX: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN]] = { inaccessiblememonly nofree nounwind willreturn } ; CHECK-DAG-LINUX: attributes [[NOFREE_NOUNWIND_READONLY_WILLRETURN]] = { nofree nounwind readonly willreturn } ; CHECK-DAG-LINUX: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY_WILLRETURN]] = { argmemonly nofree nounwind readonly willreturn } ; CHECK-DAG-LINUX: attributes [[NOFREE_NOUNWIND_READONLY_WILLRETURN]] = { argmemonly nofree nounwind willreturn } -- 2.11.0