durin42 created this revision.
Herald added subscribers: JDevlieghere, hiraditya.
Herald added a project: All.
durin42 requested review of this revision.
Herald added projects: clang, LLVM.
Herald added subscribers: llvm-commits, cfe-commits.

This allows us to remove most of the special knowledge about C++
allocation from LLVM, instead trusting attributes to communicate the
important properties.

Annoyingly, clang has to grow a little bit of hard-coded knowledge about
mangled symbol names in order to actually get the most-basic-matching
::operator::new when working out the alloc-family attribute. I spent
some time trying to do this "right" by looking up the available
operators new and finding the best one, but that's super tricky and this
has the virtue of working and being pretty obviously correct when
compared to the old code.

Happily, clang now emits allocator family attributes correctly even for
custom allocators like the one on new_hot_cold.cpp, which is similar
to tcmalloc per the comments. As a result, clang/llvm should correctly
optimize custom allocators like this without needing specialized
knowledge going forward.

Depends on D119271 <https://reviews.llvm.org/D119271>


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D152401

Files:
  clang/lib/CodeGen/CGExprCXX.cpp
  clang/test/CodeGenCXX/cxx1z-aligned-allocation.cpp
  clang/test/CodeGenCXX/new.cpp
  clang/test/CodeGenCXX/new_hot_cold.cpp
  llvm/lib/Analysis/MemoryBuiltins.cpp

Index: llvm/lib/Analysis/MemoryBuiltins.cpp
===================================================================
--- llvm/lib/Analysis/MemoryBuiltins.cpp
+++ llvm/lib/Analysis/MemoryBuiltins.cpp
@@ -110,38 +110,6 @@
 // FIXME: certain users need more information. E.g., SimplifyLibCalls needs to
 // know which functions are nounwind, noalias, nocapture parameters, etc.
 static const std::pair<LibFunc, AllocFnsTy> AllocationFnData[] = {
-    {LibFunc_Znwj,                              {OpNewLike,        1,  0, -1, -1, MallocFamily::CPPNew}},             // new(unsigned int)
-    {LibFunc_ZnwjRKSt9nothrow_t,                {MallocLike,       2,  0, -1, -1, MallocFamily::CPPNew}},             // new(unsigned int, nothrow)
-    {LibFunc_ZnwjSt11align_val_t,               {OpNewLike,        2,  0, -1,  1, MallocFamily::CPPNewAligned}},      // new(unsigned int, align_val_t)
-    {LibFunc_ZnwjSt11align_val_tRKSt9nothrow_t, {MallocLike,       3,  0, -1,  1, MallocFamily::CPPNewAligned}},      // new(unsigned int, align_val_t, nothrow)
-    {LibFunc_Znwm,                              {OpNewLike,        1,  0, -1, -1, MallocFamily::CPPNew}},             // new(unsigned long)
-    {LibFunc_Znwm12__hot_cold_t,                  {OpNewLike,        2, 0,  -1, -1, MallocFamily::CPPNew}},             // new(unsigned long, __hot_cold_t)
-    {LibFunc_ZnwmRKSt9nothrow_t,                {MallocLike,       2,  0, -1, -1, MallocFamily::CPPNew}},             // new(unsigned long, nothrow)
-    {LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t,      {MallocLike,       3, 0,  -1, -1, MallocFamily::CPPNew}},             // new(unsigned long, nothrow, __hot_cold_t)
-    {LibFunc_ZnwmSt11align_val_t,               {OpNewLike,        2,  0, -1,  1, MallocFamily::CPPNewAligned}},      // new(unsigned long, align_val_t)
-    {LibFunc_ZnwmSt11align_val_t12__hot_cold_t,   {OpNewLike,        3, 0,  -1, 1, MallocFamily::CPPNewAligned}},       // new(unsigned long, align_val_t, __hot_cold_t)
-    {LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t, {MallocLike,       3,  0, -1,  1, MallocFamily::CPPNewAligned}},      // new(unsigned long, align_val_t, nothrow)
-    {LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t, {MallocLike,  4, 0,  -1, 1, MallocFamily::CPPNewAligned}},            // new(unsigned long, align_val_t, nothrow, __hot_cold_t)
-    {LibFunc_Znaj,                              {OpNewLike,        1,  0, -1, -1, MallocFamily::CPPNewArray}},        // new[](unsigned int)
-    {LibFunc_ZnajRKSt9nothrow_t,                {MallocLike,       2,  0, -1, -1, MallocFamily::CPPNewArray}},        // new[](unsigned int, nothrow)
-    {LibFunc_ZnajSt11align_val_t,               {OpNewLike,        2,  0, -1,  1, MallocFamily::CPPNewArrayAligned}}, // new[](unsigned int, align_val_t)
-    {LibFunc_ZnajSt11align_val_tRKSt9nothrow_t, {MallocLike,       3,  0, -1,  1, MallocFamily::CPPNewArrayAligned}}, // new[](unsigned int, align_val_t, nothrow)
-    {LibFunc_Znam,                              {OpNewLike,        1,  0, -1, -1, MallocFamily::CPPNewArray}},        // new[](unsigned long)
-    {LibFunc_Znam12__hot_cold_t,                  {OpNewLike,        2, 0,  -1, -1, MallocFamily::CPPNew}},             // new[](unsigned long, __hot_cold_t)
-    {LibFunc_ZnamRKSt9nothrow_t,                {MallocLike,       2,  0, -1, -1, MallocFamily::CPPNewArray}},        // new[](unsigned long, nothrow)
-    {LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t,      {MallocLike,       3, 0,  -1, -1, MallocFamily::CPPNew}},             // new[](unsigned long, nothrow, __hot_cold_t)
-    {LibFunc_ZnamSt11align_val_t,               {OpNewLike,        2,  0, -1,  1, MallocFamily::CPPNewArrayAligned}}, // new[](unsigned long, align_val_t)
-    {LibFunc_ZnamSt11align_val_t12__hot_cold_t,   {OpNewLike,        3, 0,  -1, 1, MallocFamily::CPPNewAligned}},       // new[](unsigned long, align_val_t, __hot_cold_t)
-    {LibFunc_ZnamSt11align_val_tRKSt9nothrow_t, {MallocLike,       3,  0, -1,  1, MallocFamily::CPPNewArrayAligned}}, // new[](unsigned long, align_val_t, nothrow)
-    {LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t, {MallocLike,  4, 0,  -1, 1, MallocFamily::CPPNewAligned}},            // new[](unsigned long, align_val_t, nothrow, __hot_cold_t)
-    {LibFunc_msvc_new_int,                      {OpNewLike,        1,  0, -1, -1, MallocFamily::MSVCNew}},            // new(unsigned int)
-    {LibFunc_msvc_new_int_nothrow,              {MallocLike,       2,  0, -1, -1, MallocFamily::MSVCNew}},            // new(unsigned int, nothrow)
-    {LibFunc_msvc_new_longlong,                 {OpNewLike,        1,  0, -1, -1, MallocFamily::MSVCNew}},            // new(unsigned long long)
-    {LibFunc_msvc_new_longlong_nothrow,         {MallocLike,       2,  0, -1, -1, MallocFamily::MSVCNew}},            // new(unsigned long long, nothrow)
-    {LibFunc_msvc_new_array_int,                {OpNewLike,        1,  0, -1, -1, MallocFamily::MSVCArrayNew}},       // new[](unsigned int)
-    {LibFunc_msvc_new_array_int_nothrow,        {MallocLike,       2,  0, -1, -1, MallocFamily::MSVCArrayNew}},       // new[](unsigned int, nothrow)
-    {LibFunc_msvc_new_array_longlong,           {OpNewLike,        1,  0, -1, -1, MallocFamily::MSVCArrayNew}},       // new[](unsigned long long)
-    {LibFunc_msvc_new_array_longlong_nothrow,   {MallocLike,       2,  0, -1, -1, MallocFamily::MSVCArrayNew}},       // new[](unsigned long long, nothrow)
     {LibFunc_strdup,                            {StrDupLike,       1, -1, -1, -1, MallocFamily::Malloc}},
     {LibFunc_dunder_strdup,                     {StrDupLike,       1, -1, -1, -1, MallocFamily::Malloc}},
     {LibFunc_strndup,                           {StrDupLike,       2,  1, -1, -1, MallocFamily::Malloc}},
@@ -461,35 +429,7 @@
 
 // clang-format off
 static const std::pair<LibFunc, FreeFnsTy> FreeFnData[] = {
-    {LibFunc_ZdlPv,                              {1, MallocFamily::CPPNew}},             // operator delete(void*)
-    {LibFunc_ZdaPv,                              {1, MallocFamily::CPPNewArray}},        // operator delete[](void*)
-    {LibFunc_msvc_delete_ptr32,                  {1, MallocFamily::MSVCNew}},            // operator delete(void*)
-    {LibFunc_msvc_delete_ptr64,                  {1, MallocFamily::MSVCNew}},            // operator delete(void*)
-    {LibFunc_msvc_delete_array_ptr32,            {1, MallocFamily::MSVCArrayNew}},       // operator delete[](void*)
-    {LibFunc_msvc_delete_array_ptr64,            {1, MallocFamily::MSVCArrayNew}},       // operator delete[](void*)
-    {LibFunc_ZdlPvj,                             {2, MallocFamily::CPPNew}},             // delete(void*, uint)
-    {LibFunc_ZdlPvm,                             {2, MallocFamily::CPPNew}},             // delete(void*, ulong)
-    {LibFunc_ZdlPvRKSt9nothrow_t,                {2, MallocFamily::CPPNew}},             // delete(void*, nothrow)
-    {LibFunc_ZdlPvSt11align_val_t,               {2, MallocFamily::CPPNewAligned}},      // delete(void*, align_val_t)
-    {LibFunc_ZdaPvj,                             {2, MallocFamily::CPPNewArray}},        // delete[](void*, uint)
-    {LibFunc_ZdaPvm,                             {2, MallocFamily::CPPNewArray}},        // delete[](void*, ulong)
-    {LibFunc_ZdaPvRKSt9nothrow_t,                {2, MallocFamily::CPPNewArray}},        // delete[](void*, nothrow)
-    {LibFunc_ZdaPvSt11align_val_t,               {2, MallocFamily::CPPNewArrayAligned}}, // delete[](void*, align_val_t)
-    {LibFunc_msvc_delete_ptr32_int,              {2, MallocFamily::MSVCNew}},            // delete(void*, uint)
-    {LibFunc_msvc_delete_ptr64_longlong,         {2, MallocFamily::MSVCNew}},            // delete(void*, ulonglong)
-    {LibFunc_msvc_delete_ptr32_nothrow,          {2, MallocFamily::MSVCNew}},            // delete(void*, nothrow)
-    {LibFunc_msvc_delete_ptr64_nothrow,          {2, MallocFamily::MSVCNew}},            // delete(void*, nothrow)
-    {LibFunc_msvc_delete_array_ptr32_int,        {2, MallocFamily::MSVCArrayNew}},       // delete[](void*, uint)
-    {LibFunc_msvc_delete_array_ptr64_longlong,   {2, MallocFamily::MSVCArrayNew}},       // delete[](void*, ulonglong)
-    {LibFunc_msvc_delete_array_ptr32_nothrow,    {2, MallocFamily::MSVCArrayNew}},       // delete[](void*, nothrow)
-    {LibFunc_msvc_delete_array_ptr64_nothrow,    {2, MallocFamily::MSVCArrayNew}},       // delete[](void*, nothrow)
     {LibFunc___kmpc_free_shared,                 {2, MallocFamily::KmpcAllocShared}},    // OpenMP Offloading RTL free
-    {LibFunc_ZdlPvSt11align_val_tRKSt9nothrow_t, {3, MallocFamily::CPPNewAligned}},      // delete(void*, align_val_t, nothrow)
-    {LibFunc_ZdaPvSt11align_val_tRKSt9nothrow_t, {3, MallocFamily::CPPNewArrayAligned}}, // delete[](void*, align_val_t, nothrow)
-    {LibFunc_ZdlPvjSt11align_val_t,              {3, MallocFamily::CPPNewAligned}},      // delete(void*, unsigned int, align_val_t)
-    {LibFunc_ZdlPvmSt11align_val_t,              {3, MallocFamily::CPPNewAligned}},      // delete(void*, unsigned long, align_val_t)
-    {LibFunc_ZdaPvjSt11align_val_t,              {3, MallocFamily::CPPNewArrayAligned}}, // delete[](void*, unsigned int, align_val_t)
-    {LibFunc_ZdaPvmSt11align_val_t,              {3, MallocFamily::CPPNewArrayAligned}}, // delete[](void*, unsigned long, align_val_t)
 };
 // clang-format on
 
Index: clang/test/CodeGenCXX/new_hot_cold.cpp
===================================================================
--- clang/test/CodeGenCXX/new_hot_cold.cpp
+++ clang/test/CodeGenCXX/new_hot_cold.cpp
@@ -49,7 +49,7 @@
 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:#[^ ]*]]
+  // CHECK: call noalias noundef nonnull ptr @_Znwm12__hot_cold_t(i64 noundef 4, i8 noundef zeroext 0) [[ATTRS_ARRAY_NEW_BUILTIN:#[^ ]*]]
   new ((__hot_cold_t)0) int;
 }
 
@@ -58,7 +58,7 @@
 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:#[^ ]*]]
+  // CHECK: call noalias noundef nonnull ptr @_Znam12__hot_cold_t(i64 noundef 4, i8 noundef zeroext 0) [[ATTRS_ARRAY_NEW_BUILTIN:#[^ ]*]]
   new ((__hot_cold_t)0) int[1];
 }
 
@@ -67,7 +67,7 @@
 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:#[^ ]*]]
+  // CHECK: call noalias noundef ptr @_ZnwmRKSt9nothrow_t12__hot_cold_t(i64 noundef 4, {{.*}} @nothrow, i8 noundef zeroext 0) [[ATTRS_ARRAY_ALIGNED_NEW_BUILTIN:#[^ ]*]]
   new (nothrow, (__hot_cold_t)0) int;
 }
 
@@ -76,7 +76,7 @@
 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:#[^ ]*]]
+  // CHECK: call noalias noundef ptr @_ZnamRKSt9nothrow_t12__hot_cold_t(i64 noundef 4, {{.*}} @nothrow, i8 noundef zeroext 0) [[ATTRS_ARRAY_ALIGNED_NEW_BUILTIN:#[^ ]*]]
   new (nothrow, (__hot_cold_t)0) int[1];
 }
 
@@ -87,36 +87,36 @@
 };
 
 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:#[^ ]*]]
+  // CHECK: call noalias noundef nonnull align 32 ptr @_ZnwmSt11align_val_t12__hot_cold_t(i64 noundef 1, i64 allocalign 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:#[^ ]*]]
+  // CHECK: call noalias noundef nonnull align 32 ptr @_ZnwmSt11align_val_t12__hot_cold_t(i64 noundef 32, i64 allocalign noundef 32, i8 noundef zeroext 0) [[ATTR_BUILTIN_NEW_ALIGNED:#[^ ]*]]
   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:#[^ ]*]]
+  // CHECK: call noalias noundef nonnull align 32 ptr @_ZnamSt11align_val_t12__hot_cold_t(i64 noundef 1, i64 allocalign 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:#[^ ]*]]
+  // CHECK: call noalias noundef nonnull align 32 ptr @_ZnamSt11align_val_t12__hot_cold_t(i64 noundef 32, i64 allocalign noundef 32, i8 noundef zeroext 0) [[ATTRS_ARRAY_NEW_BUILTIN:#[^ ]*]]
   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:#[^ ]*]]
+  // CHECK: call noalias noundef align 32 ptr @_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t(i64 noundef 1, i64 allocalign 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:#[^ ]*]]
+  // CHECK: call noalias noundef align 32 ptr @_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t(i64 noundef 32, i64 allocalign noundef 32, {{.*}} @nothrow, i8 noundef zeroext 0) [[ATTRS_ARRAY_ALIGNED_NEW_BUILTIN:#[^ ]*]]
   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:#[^ ]*]]
+  // CHECK: call noalias noundef align 32 ptr @_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t(i64 noundef 1, i64 allocalign 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:#[^ ]*]]
+  // CHECK: call noalias noundef align 32 ptr @_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t(i64 noundef 32, i64 allocalign noundef 32, {{.*}} @nothrow, i8 noundef zeroext 0) [[ATTRS_ARRAY_ALIGNED_NEW_BUILTIN:#[^ ]*]]
   new (nothrow, (__hot_cold_t)0) alignedstruct[1];
 }
 
@@ -124,7 +124,7 @@
 
 // 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) }
+// CHECK-DAG: attributes [[ATTR_BUILTIN_NEW_ALIGNED]] = { builtin allockind("alloc,uninitialized,aligned") allocsize(0) "alloc-family"="_ZnwmSt11align_val_t" }
+// CHECK-DAG: attributes [[ATTRS_ARRAY_NEW_BUILTIN]] = { builtin allockind("alloc,uninitialized,aligned") allocsize(0) "alloc-family"="_ZnamSt11align_val_t" }
+// CHECK-DAG: attributes [[ATTRS_ARRAY_ALIGNED_NEW_BUILTIN]] = { builtin nounwind allockind("alloc,uninitialized,aligned") allocsize(0) "alloc-family"="_ZnamSt11align_val_t" }
Index: clang/test/CodeGenCXX/new.cpp
===================================================================
--- clang/test/CodeGenCXX/new.cpp
+++ clang/test/CodeGenCXX/new.cpp
@@ -320,9 +320,9 @@
     // CHECK: call void @_ZdlPv({{.*}}) [[ATTR_BUILTIN_DELETE:#[^ ]*]]
     delete p;
 
-    // CHECK: call noalias noundef nonnull ptr @_Znam(i64 noundef 12) [[ATTR_BUILTIN_NEW]]
+    // CHECK: call noalias noundef nonnull ptr @_Znam(i64 noundef 12) [[ATTR_BUILTIN_ARRAY_NEW:#[^ ]*]]
     int *q = new int[3];
-    // CHECK: call void @_ZdaPv({{.*}}) [[ATTR_BUILTIN_DELETE]]
+    // CHECK: call void @_ZdaPv({{.*}}) [[ATTR_BUILTIN_ARRAY_DELETE:#[^ ]*]]
     delete[] p; // expected-warning {{'delete[]' applied to a pointer that was allocated with 'new'; did you mean 'delete'?}}
 
     // CHECK: call noalias noundef ptr @_ZnamRKSt9nothrow_t(i64 noundef 3, {{.*}}) [[ATTR_NOBUILTIN_NOUNWIND_ALLOCSIZE:#[^ ]*]]
@@ -366,8 +366,11 @@
 // CHECK-DAG: attributes [[ATTR_NOBUILTIN_NOUNWIND]] = {{[{].*}} nobuiltin nounwind {{.*[}]}}
 // CHECK-DAG: attributes [[ATTR_NOBUILTIN_NOUNWIND_ALLOCSIZE]] = {{[{].*}} nobuiltin nounwind allocsize(0) {{.*[}]}}
 
-// CHECK-DAG: attributes [[ATTR_BUILTIN_NEW]] = {{[{].*}} builtin {{.*[}]}}
-// CHECK-DAG: attributes [[ATTR_BUILTIN_DELETE]] = {{[{].*}} builtin {{.*[}]}}
+// CHECK-DAG: attributes [[ATTR_BUILTIN_NEW]] = { builtin allockind("alloc,uninitialized") allocsize(0) "alloc-family"="_Znwm" }
+// CHECK-DAG: attributes [[ATTR_BUILTIN_DELETE]] = { builtin nounwind allockind("free") "alloc-family"="_Znwm" }
+
+// CHECK-DAG: attributes [[ATTR_BUILTIN_ARRAY_NEW]] = { builtin allockind("alloc,uninitialized") allocsize(0) "alloc-family"="_Znam" }
+// CHECK-DAG: attributes [[ATTR_BUILTIN_ARRAY_DELETE]] = { builtin nounwind allockind("free") "alloc-family"="_Znam" }
 
 // The ([^b}|...) monstrosity is matching a character that's not the start of 'builtin'.
 // Add more letters if this matches some other attribute.
Index: clang/test/CodeGenCXX/cxx1z-aligned-allocation.cpp
===================================================================
--- clang/test/CodeGenCXX/cxx1z-aligned-allocation.cpp
+++ clang/test/CodeGenCXX/cxx1z-aligned-allocation.cpp
@@ -58,7 +58,7 @@
 void a2(A *p) { delete p; }
 
 // CHECK-LABEL: define {{.*}} @_Z2a3P1A(
-// CHECK: call void @_ZdaPvSt11align_val_t(ptr allocptr noundef %{{.*}}, i64 noundef 32) #9
+// CHECK: call void @_ZdaPvSt11align_val_t(ptr allocptr noundef %{{.*}}, i64 noundef 32) #11
 void a3(A *p) { delete[] p; }
 
 
Index: clang/lib/CodeGen/CGExprCXX.cpp
===================================================================
--- clang/lib/CodeGen/CGExprCXX.cpp
+++ clang/lib/CodeGen/CGExprCXX.cpp
@@ -18,6 +18,7 @@
 #include "ConstantEmitter.h"
 #include "TargetInfo.h"
 #include "clang/Basic/CodeGenOptions.h"
+#include "clang/Basic/OperatorKinds.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
 #include "llvm/IR/Intrinsics.h"
 
@@ -1312,10 +1313,9 @@
   llvm::CallBase *CallOrInvoke;
   llvm::Constant *CalleePtr = CGF.CGM.GetAddrOfFunction(CalleeDecl);
   CGCallee Callee = CGCallee::forDirect(CalleePtr, GlobalDecl(CalleeDecl));
-  RValue RV =
-      CGF.EmitCall(CGF.CGM.getTypes().arrangeFreeFunctionCall(
-                       Args, CalleeType, /*ChainCall=*/false),
-                   Callee, ReturnValueSlot(), Args, &CallOrInvoke);
+  RValue RV = CGF.EmitCall(CGF.CGM.getTypes().arrangeFreeFunctionCall(
+                               Args, CalleeType, /*ChainCall=*/false),
+                           Callee, ReturnValueSlot(), Args, &CallOrInvoke);
 
   /// C++1y [expr.new]p10:
   ///   [In a new-expression,] an implementation is allowed to omit a call
@@ -1323,15 +1323,56 @@
   ///
   /// We model such elidable calls with the 'builtin' attribute.
   llvm::Function *Fn = dyn_cast<llvm::Function>(CalleePtr);
-  if (CalleeDecl->isReplaceableGlobalAllocationFunction()) {
-    if (Fn && Fn->hasFnAttribute(llvm::Attribute::NoBuiltin)) {
-      CallOrInvoke->addFnAttr(llvm::Attribute::Builtin);
+  std::optional<unsigned> AlignArg;
+  if (CalleeDecl->isReplaceableGlobalAllocationFunction(&AlignArg)) {
+    auto &Ctx = CallOrInvoke->getContext();
+    llvm::AllocFnKind AK = llvm::AllocFnKind::Unknown;
+    bool IsDeleter = CalleeDecl->getOverloadedOperator() == OO_Array_Delete ||
+                     CalleeDecl->getOverloadedOperator() == OO_Delete;
+    if (IsDeleter) {
+      AK = AK | llvm::AllocFnKind::Free;
+      CallOrInvoke->addParamAttr(0, llvm::Attribute::AllocatedPointer);
+    } else {
+      if (AlignArg)
+        AK = llvm::AllocFnKind::Aligned;
+      AK = AK | llvm::AllocFnKind::Alloc | llvm::AllocFnKind::Uninitialized;
+    }
+    ASTContext &ASTCtx = CalleeDecl->getASTContext();
+    ASTNameGenerator gen = ASTNameGenerator(ASTCtx);
+    std::string Mangled = gen.getName(CalleeDecl);
+
+    if (Mangled.find("??") == 0) {
+      // MSVC mangling
+      if (CalleeDecl->getOverloadedOperator() == clang::OO_Array_Delete ||
+          CalleeDecl->getOverloadedOperator() == clang::OO_Array_New) {
+        Mangled = "??_U@YAPAXI@Z";
+      }
+      Mangled = "??2@YAPAXI@Z";
+    } else if (Mangled.find("_Z") == 0 || Mangled.find("_Z") == 1) {
+      // LLVM Mangling
+      if (CalleeDecl->getOverloadedOperator() == clang::OO_Array_Delete ||
+          CalleeDecl->getOverloadedOperator() == clang::OO_Array_New) {
+        if (AlignArg)
+          Mangled = "_ZnamSt11align_val_t";
+        else
+          Mangled = "_Znam";
+      } else if (AlignArg)
+        Mangled = "_ZnwmSt11align_val_t";
+      else
+        Mangled = "_Znwm";
+    } else {
+      std::string msg =
+          "unknown mangling when resolving mangled form of operator::new: " +
+          Mangled;
+      llvm_unreachable(msg.c_str());
     }
 
-    if (CalleeDecl->getOverloadedOperator() == OO_Array_Delete ||
-        CalleeDecl->getOverloadedOperator() == OO_Delete) {
-      CallOrInvoke->addParamAttr(0, llvm::Attribute::AllocatedPointer);
+    CallOrInvoke->addFnAttr(llvm::Attribute::get(Ctx, "alloc-family", Mangled));
+    if (Fn && Fn->hasFnAttribute(llvm::Attribute::NoBuiltin)) {
+      CallOrInvoke->addFnAttr(llvm::Attribute::Builtin);
     }
+    CallOrInvoke->addFnAttr(llvm::Attribute::get(
+        Ctx, llvm::Attribute::AllocKind, static_cast<uint64_t>(AK)));
   }
 
   return RV;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to