
Follow up to LLVM-side change to allow conversion to hot/cold hinted operator new, not yet standard but supported by open source tcmalloc. The LLVM change in a35206d78280e0ebcf48cd21bc5fff5c3b9c73fa added the necessary support to recognize these as library functions, and we subsequently found that a clang-side change is needed to give them builtin/nobuiltin attributes as appropriate so they have consistent removeability. Based on discussion with Richard Smith, converted the parameter type to a reserved identifier (39f7b48671dae5fbe3afc49f33f50c2b6340bb89) and added support in this patch to recognize it in clang. Differential Revision: https://reviews.llvm.org/D149600
131 lines
7.5 KiB
C++
131 lines
7.5 KiB
C++
// Test to check that the appropriate attributes are added to the __hot_cold_t
|
|
// versions of operator new.
|
|
|
|
// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -faligned-allocation -emit-llvm -o - | FileCheck %s
|
|
|
|
typedef __typeof__(sizeof(0)) size_t;
|
|
|
|
namespace std {
|
|
struct nothrow_t {};
|
|
enum class align_val_t : size_t;
|
|
} // namespace std
|
|
std::nothrow_t nothrow;
|
|
|
|
typedef unsigned char uint8_t;
|
|
|
|
// See the following link for how this type is declared in tcmalloc:
|
|
// https://github.com/google/tcmalloc/blob/220043886d4e2efff7a5702d5172cb8065253664/tcmalloc/malloc_extension.h#L53.
|
|
enum class __hot_cold_t : uint8_t;
|
|
|
|
// Test handling of declaration that uses a type alias, ensuring that it still
|
|
// recognizes the expected __hot_cold_t type name.
|
|
namespace malloc_namespace {
|
|
using hot_cold_t = __hot_cold_t;
|
|
}
|
|
|
|
void *operator new(size_t size,
|
|
malloc_namespace::hot_cold_t hot_cold) noexcept(false);
|
|
void *operator new[](size_t size,
|
|
malloc_namespace::hot_cold_t hot_cold) noexcept(false);
|
|
void *operator new(size_t size, const std::nothrow_t &,
|
|
malloc_namespace::hot_cold_t hot_cold) noexcept;
|
|
void *operator new[](size_t size, const std::nothrow_t &,
|
|
malloc_namespace::hot_cold_t hot_cold) noexcept;
|
|
void *operator new(size_t size, std::align_val_t alignment,
|
|
malloc_namespace::hot_cold_t hot_cold) noexcept(false);
|
|
void *operator new[](size_t size, std::align_val_t alignment,
|
|
malloc_namespace::hot_cold_t hot_cold) noexcept(false);
|
|
void *operator new(size_t size, std::align_val_t alignment,
|
|
const std::nothrow_t &,
|
|
malloc_namespace::hot_cold_t hot_cold) noexcept;
|
|
void *operator new[](size_t size, std::align_val_t alignment,
|
|
const std::nothrow_t &,
|
|
malloc_namespace::hot_cold_t hot_cold) noexcept;
|
|
|
|
// All explicit operator new calls should not get any builtin attribute, whereas
|
|
// all implicit new expressions should get builtin attributes. All of the
|
|
// declarations should get nobuiltin attributes.
|
|
|
|
void hot_cold_new() {
|
|
// CHECK: call noalias noundef nonnull ptr @_Znwm12__hot_cold_t(i64 noundef 1, i8 noundef zeroext 0) [[ATTR_NO_BUILTIN_CALL:#[^ ]*]]
|
|
operator new(1, (__hot_cold_t)0);
|
|
// CHECK: call noalias noundef nonnull ptr @_Znwm12__hot_cold_t(i64 noundef 4, i8 noundef zeroext 0) [[ATTR_BUILTIN_CALL:#[^ ]*]]
|
|
new ((__hot_cold_t)0) int;
|
|
}
|
|
|
|
// CHECK: declare noundef nonnull ptr @_Znwm12__hot_cold_t(i64 noundef, i8 noundef zeroext) [[ATTR_NOBUILTIN:#[^ ]*]]
|
|
|
|
void hot_cold_new_array() {
|
|
// CHECK: call noalias noundef nonnull ptr @_Znam12__hot_cold_t(i64 noundef 1, i8 noundef zeroext 0) [[ATTR_NO_BUILTIN_CALL:#[^ ]*]]
|
|
operator new[](1, (__hot_cold_t)0);
|
|
// CHECK: call noalias noundef nonnull ptr @_Znam12__hot_cold_t(i64 noundef 4, i8 noundef zeroext 0) [[ATTR_BUILTIN_CALL:#[^ ]*]]
|
|
new ((__hot_cold_t)0) int[1];
|
|
}
|
|
|
|
// CHECK: declare noundef nonnull ptr @_Znam12__hot_cold_t(i64 noundef, i8 noundef zeroext) [[ATTR_NOBUILTIN:#[^ ]*]]
|
|
|
|
void hot_cold_new_nothrow() {
|
|
// CHECK: call noalias noundef ptr @_ZnwmRKSt9nothrow_t12__hot_cold_t(i64 noundef 1, {{.*}} @nothrow, i8 noundef zeroext 0) [[ATTR_NO_BUILTIN_NOTHROW_CALL:#[^ ]*]]
|
|
operator new(1, nothrow, (__hot_cold_t)0);
|
|
// CHECK: call noalias noundef ptr @_ZnwmRKSt9nothrow_t12__hot_cold_t(i64 noundef 4, {{.*}} @nothrow, i8 noundef zeroext 0) [[ATTR_BUILTIN_NOTHROW_CALL:#[^ ]*]]
|
|
new (nothrow, (__hot_cold_t)0) int;
|
|
}
|
|
|
|
// CHECK: declare noundef ptr @_ZnwmRKSt9nothrow_t12__hot_cold_t(i64 noundef, ptr noundef nonnull align 1 dereferenceable(1), i8 noundef zeroext) [[ATTR_NOBUILTIN_NOTHROW:#[^ ]*]]
|
|
|
|
void hot_cold_new_nothrow_array() {
|
|
// CHECK: call noalias noundef ptr @_ZnamRKSt9nothrow_t12__hot_cold_t(i64 noundef 1, {{.*}} @nothrow, i8 noundef zeroext 0) [[ATTR_NO_BUILTIN_NOTHROW_CALL:#[^ ]*]]
|
|
operator new[](1, nothrow, (__hot_cold_t)0);
|
|
// CHECK: call noalias noundef ptr @_ZnamRKSt9nothrow_t12__hot_cold_t(i64 noundef 4, {{.*}} @nothrow, i8 noundef zeroext 0) [[ATTR_BUILTIN_NOTHROW_CALL:#[^ ]*]]
|
|
new (nothrow, (__hot_cold_t)0) int[1];
|
|
}
|
|
|
|
// CHECK: declare noundef ptr @_ZnamRKSt9nothrow_t12__hot_cold_t(i64 noundef, ptr noundef nonnull align 1 dereferenceable(1), i8 noundef zeroext) [[ATTR_NOBUILTIN_NOTHROW:#[^ ]*]]
|
|
|
|
class alignas(32) alignedstruct {
|
|
int x;
|
|
};
|
|
|
|
void hot_cold_new_align() {
|
|
// CHECK: call noalias noundef nonnull align 32 ptr @_ZnwmSt11align_val_t12__hot_cold_t(i64 noundef 1, i64 noundef 32, i8 noundef zeroext 0) [[ATTR_NO_BUILTIN_CALL:#[^ ]*]]
|
|
operator new(1, (std::align_val_t)32, (__hot_cold_t)0);
|
|
// CHECK: call noalias noundef nonnull align 32 ptr @_ZnwmSt11align_val_t12__hot_cold_t(i64 noundef 32, i64 noundef 32, i8 noundef zeroext 0) [[ATTR_BUILTIN_CALL:#[^ ]*]]
|
|
new ((__hot_cold_t)0) alignedstruct;
|
|
}
|
|
|
|
// CHECK: declare noundef nonnull ptr @_ZnwmSt11align_val_t12__hot_cold_t(i64 noundef, i64 noundef, i8 noundef zeroext) [[ATTR_NOBUILTIN:#[^ ]*]]
|
|
|
|
void hot_cold_new_align_array() {
|
|
// CHECK: call noalias noundef nonnull align 32 ptr @_ZnamSt11align_val_t12__hot_cold_t(i64 noundef 1, i64 noundef 32, i8 noundef zeroext 0) [[ATTR_NO_BUILTIN_CALL:#[^ ]*]]
|
|
operator new[](1, (std::align_val_t)32, (__hot_cold_t)0);
|
|
// CHECK: call noalias noundef nonnull align 32 ptr @_ZnamSt11align_val_t12__hot_cold_t(i64 noundef 32, i64 noundef 32, i8 noundef zeroext 0) [[ATTR_BUILTIN_CALL:#[^ ]*]]
|
|
new ((__hot_cold_t)0) alignedstruct[1];
|
|
}
|
|
|
|
// CHECK: declare noundef nonnull ptr @_ZnamSt11align_val_t12__hot_cold_t(i64 noundef, i64 noundef, i8 noundef zeroext) [[ATTR_NOBUILTIN:#[^ ]*]]
|
|
|
|
void hot_cold_new_align_nothrow() {
|
|
// CHECK: call noalias noundef align 32 ptr @_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t(i64 noundef 1, i64 noundef 32, {{.*}} @nothrow, i8 noundef zeroext 0) [[ATTR_NO_BUILTIN_NOTHROW_CALL:#[^ ]*]]
|
|
operator new(1, (std::align_val_t)32, nothrow, (__hot_cold_t)0);
|
|
// CHECK: call noalias noundef align 32 ptr @_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t(i64 noundef 32, i64 noundef 32, {{.*}} @nothrow, i8 noundef zeroext 0) [[ATTR_BUILTIN_NOTHROW_CALL:#[^ ]*]]
|
|
new (nothrow, (__hot_cold_t)0) alignedstruct;
|
|
}
|
|
|
|
// CHECK: declare noundef ptr @_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t(i64 noundef, i64 noundef, ptr noundef nonnull align 1 dereferenceable(1), i8 noundef zeroext) [[ATTR_NOBUILTIN_NOTHROW:#[^ ]*]]
|
|
|
|
void hot_cold_new_align_nothrow_array() {
|
|
// CHECK: call noalias noundef align 32 ptr @_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t(i64 noundef 1, i64 noundef 32, {{.*}} @nothrow, i8 noundef zeroext 0) [[ATTR_NO_BUILTIN_NOTHROW_CALL:#[^ ]*]]
|
|
operator new[](1, (std::align_val_t)32, nothrow, (__hot_cold_t)0);
|
|
// CHECK: call noalias noundef align 32 ptr @_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t(i64 noundef 32, i64 noundef 32, {{.*}} @nothrow, i8 noundef zeroext 0) [[ATTR_BUILTIN_NOTHROW_CALL:#[^ ]*]]
|
|
new (nothrow, (__hot_cold_t)0) alignedstruct[1];
|
|
}
|
|
|
|
// CHECK: declare noundef ptr @_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t(i64 noundef, i64 noundef, ptr noundef nonnull align 1 dereferenceable(1), i8 noundef zeroext) [[ATTR_NOBUILTIN_NOTHROW:#[^ ]*]]
|
|
|
|
// CHECK-DAG: attributes [[ATTR_NOBUILTIN]] = { nobuiltin allocsize(0) {{.*}} }
|
|
// CHECK-DAG: attributes [[ATTR_NOBUILTIN_NOTHROW]] = { nobuiltin nounwind allocsize(0) {{.*}} }
|
|
// CHECK-DAG: attributes [[ATTR_NO_BUILTIN_CALL]] = { allocsize(0) }
|
|
// CHECK-DAG: attributes [[ATTR_BUILTIN_CALL]] = { builtin allocsize(0) }
|
|
// CHECK-DAG: attributes [[ATTR_NO_BUILTIN_NOTHROW_CALL]] = { nounwind allocsize(0) }
|
|
// CHECK-DAG: attributes [[ATTR_BUILTIN_NOTHROW_CALL]] = { builtin nounwind allocsize(0) }
|