xref: /llvm-project/clang/test/CodeGenCXX/new_hot_cold.cpp (revision 2cc0c0de802178dc7e5408497e2ec53b6c9728fa)
1 // Test to check that the appropriate attributes are added to the __hot_cold_t
2 // versions of operator new.
3 
4 // RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -faligned-allocation -emit-llvm -o - | FileCheck %s
5 
6 typedef __typeof__(sizeof(0)) size_t;
7 
8 namespace std {
9 struct nothrow_t {};
10 enum class align_val_t : size_t;
11 } // namespace std
12 std::nothrow_t nothrow;
13 
14 typedef unsigned char uint8_t;
15 
16 // See the following link for how this type is declared in tcmalloc:
17 // https://github.com/google/tcmalloc/blob/220043886d4e2efff7a5702d5172cb8065253664/tcmalloc/malloc_extension.h#L53.
18 enum class __hot_cold_t : uint8_t;
19 
20 // Test handling of declaration that uses a type alias, ensuring that it still
21 // recognizes the expected __hot_cold_t type name.
22 namespace malloc_namespace {
23 using hot_cold_t = __hot_cold_t;
24 }
25 
26 void *operator new(size_t size,
27                    malloc_namespace::hot_cold_t hot_cold) noexcept(false);
28 void *operator new[](size_t size,
29                      malloc_namespace::hot_cold_t hot_cold) noexcept(false);
30 void *operator new(size_t size, const std::nothrow_t &,
31                    malloc_namespace::hot_cold_t hot_cold) noexcept;
32 void *operator new[](size_t size, const std::nothrow_t &,
33                      malloc_namespace::hot_cold_t hot_cold) noexcept;
34 void *operator new(size_t size, std::align_val_t alignment,
35                    malloc_namespace::hot_cold_t hot_cold) noexcept(false);
36 void *operator new[](size_t size, std::align_val_t alignment,
37                      malloc_namespace::hot_cold_t hot_cold) noexcept(false);
38 void *operator new(size_t size, std::align_val_t alignment,
39                    const std::nothrow_t &,
40                    malloc_namespace::hot_cold_t hot_cold) noexcept;
41 void *operator new[](size_t size, std::align_val_t alignment,
42                      const std::nothrow_t &,
43                      malloc_namespace::hot_cold_t hot_cold) noexcept;
44 
45 // All explicit operator new calls should not get any builtin attribute, whereas
46 // all implicit new expressions should get builtin attributes. All of the
47 // declarations should get nobuiltin attributes.
48 
hot_cold_new()49 void hot_cold_new() {
50   // CHECK: call noalias noundef nonnull ptr @_Znwm12__hot_cold_t(i64 noundef 1, i8 noundef zeroext 0) [[ATTR_NO_BUILTIN_CALL:#[^ ]*]]
51   operator new(1, (__hot_cold_t)0);
52   // CHECK: call noalias noundef nonnull ptr @_Znwm12__hot_cold_t(i64 noundef 4, i8 noundef zeroext 0) [[ATTR_BUILTIN_CALL:#[^ ]*]]
53   new ((__hot_cold_t)0) int;
54 }
55 
56 // CHECK: declare noundef nonnull ptr @_Znwm12__hot_cold_t(i64 noundef, i8 noundef zeroext) [[ATTR_NOBUILTIN:#[^ ]*]]
57 
hot_cold_new_array()58 void hot_cold_new_array() {
59   // CHECK: call noalias noundef nonnull ptr @_Znam12__hot_cold_t(i64 noundef 1, i8 noundef zeroext 0) [[ATTR_NO_BUILTIN_CALL:#[^ ]*]]
60   operator new[](1, (__hot_cold_t)0);
61   // CHECK: call noalias noundef nonnull ptr @_Znam12__hot_cold_t(i64 noundef 4, i8 noundef zeroext 0) [[ATTR_BUILTIN_CALL:#[^ ]*]]
62   new ((__hot_cold_t)0) int[1];
63 }
64 
65 // CHECK: declare noundef nonnull ptr @_Znam12__hot_cold_t(i64 noundef, i8 noundef zeroext) [[ATTR_NOBUILTIN:#[^ ]*]]
66 
hot_cold_new_nothrow()67 void hot_cold_new_nothrow() {
68   // CHECK: call noalias noundef ptr @_ZnwmRKSt9nothrow_t12__hot_cold_t(i64 noundef 1, {{.*}} @nothrow, i8 noundef zeroext 0) [[ATTR_NO_BUILTIN_NOTHROW_CALL:#[^ ]*]]
69   operator new(1, nothrow, (__hot_cold_t)0);
70   // CHECK: call noalias noundef ptr @_ZnwmRKSt9nothrow_t12__hot_cold_t(i64 noundef 4, {{.*}} @nothrow, i8 noundef zeroext 0) [[ATTR_BUILTIN_NOTHROW_CALL:#[^ ]*]]
71   new (nothrow, (__hot_cold_t)0) int;
72 }
73 
74 // CHECK: declare noundef ptr @_ZnwmRKSt9nothrow_t12__hot_cold_t(i64 noundef, ptr noundef nonnull align 1 dereferenceable(1), i8 noundef zeroext) [[ATTR_NOBUILTIN_NOTHROW:#[^ ]*]]
75 
hot_cold_new_nothrow_array()76 void hot_cold_new_nothrow_array() {
77   // CHECK: call noalias noundef ptr @_ZnamRKSt9nothrow_t12__hot_cold_t(i64 noundef 1, {{.*}} @nothrow, i8 noundef zeroext 0) [[ATTR_NO_BUILTIN_NOTHROW_CALL:#[^ ]*]]
78   operator new[](1, nothrow, (__hot_cold_t)0);
79   // CHECK: call noalias noundef ptr @_ZnamRKSt9nothrow_t12__hot_cold_t(i64 noundef 4, {{.*}} @nothrow, i8 noundef zeroext 0) [[ATTR_BUILTIN_NOTHROW_CALL:#[^ ]*]]
80   new (nothrow, (__hot_cold_t)0) int[1];
81 }
82 
83 // CHECK: declare noundef ptr @_ZnamRKSt9nothrow_t12__hot_cold_t(i64 noundef, ptr noundef nonnull align 1 dereferenceable(1), i8 noundef zeroext) [[ATTR_NOBUILTIN_NOTHROW:#[^ ]*]]
84 
85 class alignas(32) alignedstruct {
86   int x;
87 };
88 
hot_cold_new_align()89 void hot_cold_new_align() {
90   // 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:#[^ ]*]]
91   operator new(1, (std::align_val_t)32, (__hot_cold_t)0);
92   // 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:#[^ ]*]]
93   new ((__hot_cold_t)0) alignedstruct;
94 }
95 
96 // CHECK: declare noundef nonnull ptr @_ZnwmSt11align_val_t12__hot_cold_t(i64 noundef, i64 noundef, i8 noundef zeroext) [[ATTR_NOBUILTIN:#[^ ]*]]
97 
hot_cold_new_align_array()98 void hot_cold_new_align_array() {
99   // 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:#[^ ]*]]
100   operator new[](1, (std::align_val_t)32, (__hot_cold_t)0);
101   // 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:#[^ ]*]]
102   new ((__hot_cold_t)0) alignedstruct[1];
103 }
104 
105 // CHECK: declare noundef nonnull ptr @_ZnamSt11align_val_t12__hot_cold_t(i64 noundef, i64 noundef, i8 noundef zeroext) [[ATTR_NOBUILTIN:#[^ ]*]]
106 
hot_cold_new_align_nothrow()107 void hot_cold_new_align_nothrow() {
108   // 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:#[^ ]*]]
109   operator new(1, (std::align_val_t)32, nothrow, (__hot_cold_t)0);
110   // 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:#[^ ]*]]
111   new (nothrow, (__hot_cold_t)0) alignedstruct;
112 }
113 
114 // 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:#[^ ]*]]
115 
hot_cold_new_align_nothrow_array()116 void hot_cold_new_align_nothrow_array() {
117   // 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:#[^ ]*]]
118   operator new[](1, (std::align_val_t)32, nothrow, (__hot_cold_t)0);
119   // 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:#[^ ]*]]
120   new (nothrow, (__hot_cold_t)0) alignedstruct[1];
121 }
122 
123 // 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:#[^ ]*]]
124 
125 // CHECK-DAG: attributes [[ATTR_NOBUILTIN]] = { nobuiltin allocsize(0) {{.*}} }
126 // CHECK-DAG: attributes [[ATTR_NOBUILTIN_NOTHROW]] = { nobuiltin nounwind allocsize(0) {{.*}} }
127 // CHECK-DAG: attributes [[ATTR_NO_BUILTIN_CALL]] = { allocsize(0) }
128 // CHECK-DAG: attributes [[ATTR_BUILTIN_CALL]] = { builtin allocsize(0) }
129 // CHECK-DAG: attributes [[ATTR_NO_BUILTIN_NOTHROW_CALL]] = { nounwind allocsize(0) }
130 // CHECK-DAG: attributes [[ATTR_BUILTIN_NOTHROW_CALL]] = { builtin nounwind allocsize(0) }
131