https://github.com/melver updated https://github.com/llvm/llvm-project/pull/169358
>From d596966645e76f444cea4f6e4377848209b6cbc5 Mon Sep 17 00:00:00 2001 From: Marco Elver <[email protected]> Date: Mon, 24 Nov 2025 17:36:32 +0100 Subject: [PATCH 1/2] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20ch?= =?UTF-8?q?anges=20to=20main=20this=20commit=20is=20based=20on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.8-beta.1 [skip ci] --- clang/test/CodeGen/memprof-pgho.cpp | 61 ++++++++++++++ .../lib/Transforms/Utils/SimplifyLibCalls.cpp | 80 ++++++++++--------- .../InstCombine/simplify-libcalls-new.ll | 13 +++ 3 files changed, 117 insertions(+), 37 deletions(-) create mode 100644 clang/test/CodeGen/memprof-pgho.cpp diff --git a/clang/test/CodeGen/memprof-pgho.cpp b/clang/test/CodeGen/memprof-pgho.cpp new file mode 100644 index 0000000000000..73bec2b303f13 --- /dev/null +++ b/clang/test/CodeGen/memprof-pgho.cpp @@ -0,0 +1,61 @@ +// Test end-to-end optimization pipeline with PGHO, that it does not interfere +// with other allocation instrumentation features. +// +// RUN: split-file %s %t +// RUN: llvm-profdata merge %t/memprof.yaml -o %t/use.profdata +// RUN: %clang_cc1 -O2 -debug-info-kind=limited -fmemory-profile-use=%t/use.profdata -mllvm -optimize-hot-cold-new \ +// RUN: %t/src.cpp -triple x86_64-linux-gnu -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,DEFAULT +// RUN: %clang_cc1 -O2 -fsanitize=alloc-token -debug-info-kind=limited -fmemory-profile-use=%t/use.profdata -mllvm -optimize-hot-cold-new \ +// RUN: %t/src.cpp -triple x86_64-linux-gnu -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,ALLOCTOKEN + +//--- memprof.yaml +--- +HeapProfileRecords: + - GUID: 0x7f8d88fcc70a347b + AllocSites: + - Callstack: + - { Function: 0x7f8d88fcc70a347b, LineOffset: 1, Column: 10, IsInlineFrame: false } + - { Function: 0xdb956436e78dd5fa, LineOffset: 1, Column: 13, IsInlineFrame: false } + MemInfoBlock: + AllocCount: 1 + TotalAccessCount: 0 + MinAccessCount: 0 + MaxAccessCount: 0 + TotalSize: 10 + MinSize: 10 + MaxSize: 10 + AllocTimestamp: 100 + DeallocTimestamp: 100 + TotalLifetime: 100000 + MinLifetime: 100000 + MaxLifetime: 100000 + AllocCpuId: 0 + DeallocCpuId: 0 + NumMigratedCpu: 0 + NumLifetimeOverlaps: 0 + NumSameAllocCpu: 0 + NumSameDeallocCpu: 0 + DataTypeId: 0 + TotalAccessDensity: 0 + MinAccessDensity: 0 + MaxAccessDensity: 0 + TotalLifetimeAccessDensity: 0 + MinLifetimeAccessDensity: 0 + MaxLifetimeAccessDensity: 0 + AccessHistogramSize: 0 + AccessHistogram: 0 +... + +//--- src.cpp +// CHECK-LABEL: define{{.*}} ptr @_Z3foov() +// DEFAULT: call {{.*}} ptr @_Znam12__hot_cold_t(i64 10, i8 -128) +// ALLOCTOKEN: call {{.*}} ptr @__alloc_token__Znam12__hot_cold_t(i64 10, i8 -128, i64 1538840549748785101){{.*}} !alloc_token +char *foo() { + return new char[10]; +} + +int main() { + char *a = foo(); + delete[] a; + return 0; +} diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp index 4f4e64b1c7b70..4ba4e484fb77d 100644 --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -1806,119 +1806,125 @@ Value *LibCallSimplifier::optimizeNew(CallInst *CI, IRBuilderBase &B, // better to replace the hinted call with a non hinted call, to avoid the // extra parameter and the if condition check of the hint value in the // allocator. This can be considered in the future. + Value *NewCall = nullptr; switch (Func) { case LibFunc_Znwm12__hot_cold_t: if (OptimizeExistingHotColdNew) - return emitHotColdNew(CI->getArgOperand(0), B, TLI, - LibFunc_Znwm12__hot_cold_t, HotCold); + NewCall = emitHotColdNew(CI->getArgOperand(0), B, TLI, + LibFunc_Znwm12__hot_cold_t, HotCold); break; case LibFunc_Znwm: - return emitHotColdNew(CI->getArgOperand(0), B, TLI, - LibFunc_Znwm12__hot_cold_t, HotCold); + NewCall = emitHotColdNew(CI->getArgOperand(0), B, TLI, + LibFunc_Znwm12__hot_cold_t, HotCold); break; case LibFunc_Znam12__hot_cold_t: if (OptimizeExistingHotColdNew) - return emitHotColdNew(CI->getArgOperand(0), B, TLI, - LibFunc_Znam12__hot_cold_t, HotCold); + NewCall = emitHotColdNew(CI->getArgOperand(0), B, TLI, + LibFunc_Znam12__hot_cold_t, HotCold); break; case LibFunc_Znam: - return emitHotColdNew(CI->getArgOperand(0), B, TLI, - LibFunc_Znam12__hot_cold_t, HotCold); + NewCall = emitHotColdNew(CI->getArgOperand(0), B, TLI, + LibFunc_Znam12__hot_cold_t, HotCold); break; case LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t: if (OptimizeExistingHotColdNew) - return emitHotColdNewNoThrow( + NewCall = emitHotColdNewNoThrow( CI->getArgOperand(0), CI->getArgOperand(1), B, TLI, LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t, HotCold); break; case LibFunc_ZnwmRKSt9nothrow_t: - return emitHotColdNewNoThrow(CI->getArgOperand(0), CI->getArgOperand(1), B, - TLI, LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t, - HotCold); + NewCall = emitHotColdNewNoThrow( + CI->getArgOperand(0), CI->getArgOperand(1), B, TLI, + LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t, HotCold); break; case LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t: if (OptimizeExistingHotColdNew) - return emitHotColdNewNoThrow( + NewCall = emitHotColdNewNoThrow( CI->getArgOperand(0), CI->getArgOperand(1), B, TLI, LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t, HotCold); break; case LibFunc_ZnamRKSt9nothrow_t: - return emitHotColdNewNoThrow(CI->getArgOperand(0), CI->getArgOperand(1), B, - TLI, LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t, - HotCold); + NewCall = emitHotColdNewNoThrow( + CI->getArgOperand(0), CI->getArgOperand(1), B, TLI, + LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t, HotCold); break; case LibFunc_ZnwmSt11align_val_t12__hot_cold_t: if (OptimizeExistingHotColdNew) - return emitHotColdNewAligned( + NewCall = emitHotColdNewAligned( CI->getArgOperand(0), CI->getArgOperand(1), B, TLI, LibFunc_ZnwmSt11align_val_t12__hot_cold_t, HotCold); break; case LibFunc_ZnwmSt11align_val_t: - return emitHotColdNewAligned(CI->getArgOperand(0), CI->getArgOperand(1), B, - TLI, LibFunc_ZnwmSt11align_val_t12__hot_cold_t, - HotCold); + NewCall = emitHotColdNewAligned( + CI->getArgOperand(0), CI->getArgOperand(1), B, TLI, + LibFunc_ZnwmSt11align_val_t12__hot_cold_t, HotCold); break; case LibFunc_ZnamSt11align_val_t12__hot_cold_t: if (OptimizeExistingHotColdNew) - return emitHotColdNewAligned( + NewCall = emitHotColdNewAligned( CI->getArgOperand(0), CI->getArgOperand(1), B, TLI, LibFunc_ZnamSt11align_val_t12__hot_cold_t, HotCold); break; case LibFunc_ZnamSt11align_val_t: - return emitHotColdNewAligned(CI->getArgOperand(0), CI->getArgOperand(1), B, - TLI, LibFunc_ZnamSt11align_val_t12__hot_cold_t, - HotCold); + NewCall = emitHotColdNewAligned( + CI->getArgOperand(0), CI->getArgOperand(1), B, TLI, + LibFunc_ZnamSt11align_val_t12__hot_cold_t, HotCold); break; case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t: if (OptimizeExistingHotColdNew) - return emitHotColdNewAlignedNoThrow( + NewCall = emitHotColdNewAlignedNoThrow( CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2), B, TLI, LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t, HotCold); break; case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t: - return emitHotColdNewAlignedNoThrow( + NewCall = emitHotColdNewAlignedNoThrow( CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2), B, TLI, LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t, HotCold); break; case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t: if (OptimizeExistingHotColdNew) - return emitHotColdNewAlignedNoThrow( + NewCall = emitHotColdNewAlignedNoThrow( CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2), B, TLI, LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t, HotCold); break; case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t: - return emitHotColdNewAlignedNoThrow( + NewCall = emitHotColdNewAlignedNoThrow( CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2), B, TLI, LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t, HotCold); break; case LibFunc_size_returning_new: - return emitHotColdSizeReturningNew(CI->getArgOperand(0), B, TLI, - LibFunc_size_returning_new_hot_cold, - HotCold); + NewCall = emitHotColdSizeReturningNew(CI->getArgOperand(0), B, TLI, + LibFunc_size_returning_new_hot_cold, + HotCold); break; case LibFunc_size_returning_new_hot_cold: if (OptimizeExistingHotColdNew) - return emitHotColdSizeReturningNew(CI->getArgOperand(0), B, TLI, - LibFunc_size_returning_new_hot_cold, - HotCold); + NewCall = emitHotColdSizeReturningNew(CI->getArgOperand(0), B, TLI, + LibFunc_size_returning_new_hot_cold, + HotCold); break; case LibFunc_size_returning_new_aligned: - return emitHotColdSizeReturningNewAligned( + NewCall = emitHotColdSizeReturningNewAligned( CI->getArgOperand(0), CI->getArgOperand(1), B, TLI, LibFunc_size_returning_new_aligned_hot_cold, HotCold); break; case LibFunc_size_returning_new_aligned_hot_cold: if (OptimizeExistingHotColdNew) - return emitHotColdSizeReturningNewAligned( + NewCall = emitHotColdSizeReturningNewAligned( CI->getArgOperand(0), CI->getArgOperand(1), B, TLI, LibFunc_size_returning_new_aligned_hot_cold, HotCold); break; default: return nullptr; } - return nullptr; + + if (auto *NewCI = dyn_cast_or_null<Instruction>(NewCall)) + if (MDNode *MD = CI->getMetadata(LLVMContext::MD_alloc_token)) + NewCI->setMetadata(LLVMContext::MD_alloc_token, MD); + + return NewCall; } //===----------------------------------------------------------------------===// diff --git a/llvm/test/Transforms/InstCombine/simplify-libcalls-new.ll b/llvm/test/Transforms/InstCombine/simplify-libcalls-new.ll index 5a4fb04f5f2c0..2765c75f4d5e0 100644 --- a/llvm/test/Transforms/InstCombine/simplify-libcalls-new.ll +++ b/llvm/test/Transforms/InstCombine/simplify-libcalls-new.ll @@ -610,6 +610,16 @@ define void @size_returning_aligned_update_test() { ret void } +;; Check that !alloc_token is preserved. +; HOTCOLD-LABEL: @new_alloc_token() +define void @new_alloc_token() { + ;; Attribute cold converted to __hot_cold_t cold value. + ; HOTCOLD: @_Znwm12__hot_cold_t(i64 10, i8 [[COLD]]), !alloc_token ![[ALLOC_TOKEN:[0-9]+]] + %call = call ptr @_Znwm(i64 10) #0, !alloc_token !0 + call void @dummy(ptr %call) + ret void +} + ;; So that instcombine doesn't optimize out the call. declare void @dummy(ptr) @@ -649,3 +659,6 @@ attributes #5 = { "memprof" = "hot" } attributes #8 = { "memprof" = "ambiguous" } attributes #6 = { nobuiltin allocsize(0) "memprof"="cold" } + +; CHECK: [[ALLOC_TOKEN]] = !{!"MyType", i1 false} +!0 = !{!"MyType", i1 false} >From 451e91c58d92250121da33136a6db9597644f50d Mon Sep 17 00:00:00 2001 From: Marco Elver <[email protected]> Date: Tue, 25 Nov 2025 15:31:35 +0100 Subject: [PATCH 2/2] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20ch?= =?UTF-8?q?anges=20introduced=20through=20rebase?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.8-beta.1 [skip ci] --- llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp index 4ba4e484fb77d..d1548694baa27 100644 --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -1921,8 +1921,7 @@ Value *LibCallSimplifier::optimizeNew(CallInst *CI, IRBuilderBase &B, } if (auto *NewCI = dyn_cast_or_null<Instruction>(NewCall)) - if (MDNode *MD = CI->getMetadata(LLVMContext::MD_alloc_token)) - NewCI->setMetadata(LLVMContext::MD_alloc_token, MD); + NewCI->copyMetadata(*CI); return NewCall; } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
