[llvm] [MergeFunctions] Fix build failure in PR #202218 (PR #206651)
Alok Kumar Sharma via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 29 23:00:38 PDT 2026
https://github.com/alokkrsharma created https://github.com/llvm/llvm-project/pull/206651
Address the build issue that caused the original change to be reverted and reapply the fix.
>From d32ef3aca1f70aa3d22eafe91605959e49ecc8a4 Mon Sep 17 00:00:00 2001
From: Alok Kumar Sharma <AlokKumar.Sharma at amd.com>
Date: Sun, 7 Jun 2026 22:01:43 +0530
Subject: [PATCH 1/3] [MergeFunctions] Preserve entry counts on folds
When folding two equivalent functions, keep profile entry count
metadata meaningful by combining the entry counts of the folded
functions on the surviving implementation.
---
llvm/lib/Transforms/IPO/MergeFunctions.cpp | 34 ++
.../MergeFunc/merge-functions-entry-count.ll | 330 ++++++++++++++++++
2 files changed, 364 insertions(+)
create mode 100644 llvm/test/Transforms/MergeFunc/merge-functions-entry-count.ll
diff --git a/llvm/lib/Transforms/IPO/MergeFunctions.cpp b/llvm/lib/Transforms/IPO/MergeFunctions.cpp
index 5c8624ba56a27..8110653aac88e 100644
--- a/llvm/lib/Transforms/IPO/MergeFunctions.cpp
+++ b/llvm/lib/Transforms/IPO/MergeFunctions.cpp
@@ -114,6 +114,7 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Utils/FunctionComparator.h"
@@ -121,6 +122,7 @@
#include <algorithm>
#include <cassert>
#include <iterator>
+#include <optional>
#include <set>
#include <utility>
#include <vector>
@@ -732,6 +734,7 @@ static void copyMetadataIfPresent(Function *From, Function *To,
// For better debugability, under MergeFunctionsPDI, we do not modify G's
// call sites to point to F even when within the same translation unit.
void MergeFunctions::writeThunk(Function *F, Function *G) {
+ auto GEC = G->getEntryCount(/*AllowSynthetic=*/true);
BasicBlock *GEntryBlock = nullptr;
std::vector<Instruction *> PDIUnrelatedWL;
std::vector<DbgVariableRecord *> PDVRUnrelatedWL;
@@ -801,6 +804,8 @@ void MergeFunctions::writeThunk(Function *F, Function *G) {
<< G->getName() << "()\n");
} else {
NewG->copyAttributesFrom(G);
+ if (GEC)
+ NewG->setEntryCount(*GEC);
NewG->takeName(G);
// Ensure CFI type metadata is propagated to the new function.
copyMetadataIfPresent(G, NewG, "type");
@@ -874,6 +879,25 @@ static bool isODR(const Function *F) {
return F->hasWeakODRLinkage() || F->hasLinkOnceODRLinkage();
}
+static void mergeEntryCountsInto(Function *F,
+ std::optional<Function::ProfileCount> FC,
+ std::optional<Function::ProfileCount> GC) {
+ if (!FC && !GC)
+ return;
+ uint64_t Sum = SaturatingAdd(FC ? FC->getCount() : uint64_t{0},
+ GC ? GC->getCount() : uint64_t{0});
+ Function::ProfileCountType PCT =
+ ((FC && FC->isSynthetic()) || (GC && GC->isSynthetic()))
+ ? Function::PCT_Synthetic
+ : Function::PCT_Real;
+ if (FC && FC->getType() != PCT) {
+ F->setMetadata(LLVMContext::MD_prof, nullptr);
+ F->setEntryCount(Function::ProfileCount(Sum, PCT));
+ return;
+ }
+ F->setEntryCount(Sum, PCT);
+}
+
// Merge two equivalent functions. Upon completion, Function G is deleted.
void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) {
@@ -902,6 +926,8 @@ void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) {
// Ensure CFI type metadata is propagated to the new function.
copyMetadataIfPresent(F, NewF, "type");
copyMetadataIfPresent(F, NewF, "kcfi_type");
+ auto FEC = F->getEntryCount(/*AllowSynthetic=*/true);
+ auto GEC = G->getEntryCount(/*AllowSynthetic=*/true);
removeUsers(F);
F->replaceAllUsesWith(NewF);
@@ -918,6 +944,8 @@ void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) {
const MaybeAlign GAlign = G->getAlign();
writeThunkOrAliasIfNeeded(F, G);
+ if (FEC)
+ NewF->setEntryCount(*FEC);
writeThunkOrAliasIfNeeded(F, NewF);
if (NewFAlign || GAlign)
@@ -925,9 +953,13 @@ void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) {
else
F->setAlignment(std::nullopt);
F->setLinkage(GlobalValue::PrivateLinkage);
+ mergeEntryCountsInto(F, FEC, GEC);
++NumDoubleWeak;
++NumFunctionsMerged;
} else {
+ auto FEC = F->getEntryCount(/*AllowSynthetic=*/true);
+ auto GEC = G->getEntryCount(/*AllowSynthetic=*/true);
+
// For better debugability, under MergeFunctionsPDI, we do not modify G's
// call sites to point to F even when within the same translation unit.
if (!G->isInterposable() && !MergeFunctionsPDI) {
@@ -952,12 +984,14 @@ void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) {
// stop here and delete G. There's no need for a thunk. (See note on
// MergeFunctionsPDI above).
if (G->isDiscardableIfUnused() && G->use_empty() && !MergeFunctionsPDI) {
+ mergeEntryCountsInto(F, FEC, GEC);
G->eraseFromParent();
++NumFunctionsMerged;
return;
}
if (writeThunkOrAliasIfNeeded(F, G)) {
+ mergeEntryCountsInto(F, FEC, GEC);
++NumFunctionsMerged;
}
}
diff --git a/llvm/test/Transforms/MergeFunc/merge-functions-entry-count.ll b/llvm/test/Transforms/MergeFunc/merge-functions-entry-count.ll
new file mode 100644
index 0000000000000..7bcab278b7055
--- /dev/null
+++ b/llvm/test/Transforms/MergeFunc/merge-functions-entry-count.ll
@@ -0,0 +1,330 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --include-generated-funcs --version 5
+; RUN: opt -S -passes=mergefunc < %s | FileCheck %s
+; RUN: opt -S -passes=mergefunc -mergefunc-use-aliases < %s | FileCheck %s --check-prefix=ALIAS
+
+define internal i32 @basic_a(i32 %x) !prof !1 {
+entry:
+ %add = add nsw i32 %x, 1
+ ret i32 %add
+}
+
+define internal i32 @basic_b(i32 %x) !prof !1 {
+entry:
+ %add = add nsw i32 %x, 1
+ ret i32 %add
+}
+
+define internal i32 @asym_a(i32 %x) !prof !2 {
+entry:
+ %add = add nsw i32 %x, 2
+ ret i32 %add
+}
+
+define internal i32 @asym_b(i32 %x) !prof !3 {
+entry:
+ %add = add nsw i32 %x, 2
+ ret i32 %add
+}
+
+define internal i32 @onesided_a(i32 %x) {
+entry:
+ %add = add nsw i32 %x, 3
+ ret i32 %add
+}
+
+define internal i32 @onesided_b(i32 %x) !prof !4 {
+entry:
+ %add = add nsw i32 %x, 3
+ ret i32 %add
+}
+
+define internal i32 @real_synth_a(i32 %x) !prof !5 {
+entry:
+ %add = add nsw i32 %x, 4
+ ret i32 %add
+}
+
+define internal i32 @real_synth_b(i32 %x) !prof !6 {
+entry:
+ %add = add nsw i32 %x, 4
+ ret i32 %add
+}
+
+define linkonce_odr i32 @odr_a(i32 %x) !prof !1 {
+entry:
+ %add = add nsw i32 %x, 5
+ ret i32 %add
+}
+
+define linkonce_odr i32 @odr_b(i32 %x) !prof !1 {
+entry:
+ %add = add nsw i32 %x, 5
+ ret i32 %add
+}
+
+ at llvm.used = appending global [2 x ptr] [ptr @odr_a, ptr @odr_b], section "llvm.metadata"
+
+define void @alias_a() unnamed_addr !prof !7 {
+ ret void
+}
+
+define void @alias_b() unnamed_addr !prof !8 {
+ ret void
+}
+
+define i32 @use_counts(i32 %x) {
+entry:
+ %basic = call i32 @basic_a(i32 %x)
+ %basic2 = call i32 @basic_b(i32 %x)
+ %asym = call i32 @asym_a(i32 %x)
+ %asym2 = call i32 @asym_b(i32 %x)
+ %onesided = call i32 @onesided_a(i32 %x)
+ %onesided2 = call i32 @onesided_b(i32 %x)
+ %real_synth = call i32 @real_synth_a(i32 %x)
+ %real_synth2 = call i32 @real_synth_b(i32 %x)
+ %odr = call i32 @odr_a(i32 %x)
+ %odr2 = call i32 @odr_b(i32 %x)
+ call void @alias_a()
+ call void @alias_b()
+ %sum0 = add i32 %basic, %basic2
+ %sum1 = add i32 %sum0, %asym
+ %sum2 = add i32 %sum1, %asym2
+ %sum3 = add i32 %sum2, %onesided
+ %sum4 = add i32 %sum3, %onesided2
+ %sum5 = add i32 %sum4, %real_synth
+ %sum6 = add i32 %sum5, %real_synth2
+ %sum7 = add i32 %sum6, %odr
+ %sum8 = add i32 %sum7, %odr2
+ ret i32 %sum8
+}
+
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 1, !"ProfileSummary", !9}
+!1 = !{!"function_entry_count", i64 1}
+!2 = !{!"function_entry_count", i64 2000}
+!3 = !{!"function_entry_count", i64 1000}
+!4 = !{!"function_entry_count", i64 500}
+!5 = !{!"function_entry_count", i64 10}
+!6 = !{!"synthetic_function_entry_count", i64 5}
+!7 = !{!"function_entry_count", i64 7}
+!8 = !{!"function_entry_count", i64 5}
+!9 = !{!10, !11, !12, !13, !14, !15, !16, !17}
+!10 = !{!"ProfileFormat", !"InstrProf"}
+!11 = !{!"TotalCount", i64 3531}
+!12 = !{!"MaxCount", i64 2000}
+!13 = !{!"MaxInternalCount", i64 2000}
+!14 = !{!"MaxFunctionCount", i64 2000}
+!15 = !{!"NumCounts", i64 12}
+!16 = !{!"NumFunctions", i64 12}
+!17 = !{!"DetailedSummary", !18}
+!18 = !{!19}
+!19 = !{i32 10000, i64 1, i32 1}
+;.
+; CHECK: @llvm.used = appending global [2 x ptr] [ptr @odr_a, ptr @odr_b], section "llvm.metadata"
+;.
+; ALIAS: @llvm.used = appending global [2 x ptr] [ptr @odr_a, ptr @odr_b], section "llvm.metadata"
+; ALIAS: @alias_b = unnamed_addr alias void (), ptr @alias_a
+;.
+; CHECK-LABEL: define internal i32 @basic_a(
+; CHECK-SAME: i32 [[X:%.*]]) !prof [[PROF12:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], 1
+; CHECK-NEXT: ret i32 [[ADD]]
+;
+;
+; CHECK-LABEL: define internal i32 @asym_a(
+; CHECK-SAME: i32 [[X:%.*]]) !prof [[PROF13:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], 2
+; CHECK-NEXT: ret i32 [[ADD]]
+;
+;
+; CHECK-LABEL: define internal i32 @onesided_a(
+; CHECK-SAME: i32 [[X:%.*]]) !prof [[PROF14:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], 3
+; CHECK-NEXT: ret i32 [[ADD]]
+;
+;
+; CHECK-LABEL: define internal i32 @real_synth_a(
+; CHECK-SAME: i32 [[X:%.*]]) !prof [[PROF15:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], 4
+; CHECK-NEXT: ret i32 [[ADD]]
+;
+;
+; CHECK-LABEL: define private i32 @0(
+; CHECK-SAME: i32 [[X:%.*]]) !prof [[PROF12]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], 5
+; CHECK-NEXT: ret i32 [[ADD]]
+;
+;
+; CHECK-LABEL: define void @alias_a(
+; CHECK-SAME: ) unnamed_addr !prof [[PROF16:![0-9]+]] {
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define void @alias_b(
+; CHECK-SAME: ) unnamed_addr !prof [[PROF17:![0-9]+]] {
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define i32 @use_counts(
+; CHECK-SAME: i32 [[X:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[BASIC:%.*]] = call i32 @basic_a(i32 [[X]])
+; CHECK-NEXT: [[BASIC2:%.*]] = call i32 @basic_a(i32 [[X]])
+; CHECK-NEXT: [[ASYM:%.*]] = call i32 @asym_a(i32 [[X]])
+; CHECK-NEXT: [[ASYM2:%.*]] = call i32 @asym_a(i32 [[X]])
+; CHECK-NEXT: [[ONESIDED:%.*]] = call i32 @onesided_a(i32 [[X]])
+; CHECK-NEXT: [[ONESIDED2:%.*]] = call i32 @onesided_a(i32 [[X]])
+; CHECK-NEXT: [[REAL_SYNTH:%.*]] = call i32 @real_synth_a(i32 [[X]])
+; CHECK-NEXT: [[REAL_SYNTH2:%.*]] = call i32 @real_synth_a(i32 [[X]])
+; CHECK-NEXT: [[ODR:%.*]] = call i32 @[[GLOB0:[0-9]+]](i32 [[X]])
+; CHECK-NEXT: [[ODR2:%.*]] = call i32 @[[GLOB0]](i32 [[X]])
+; CHECK-NEXT: call void @alias_a()
+; CHECK-NEXT: call void @alias_a()
+; CHECK-NEXT: [[SUM0:%.*]] = add i32 [[BASIC]], [[BASIC2]]
+; CHECK-NEXT: [[SUM1:%.*]] = add i32 [[SUM0]], [[ASYM]]
+; CHECK-NEXT: [[SUM2:%.*]] = add i32 [[SUM1]], [[ASYM2]]
+; CHECK-NEXT: [[SUM3:%.*]] = add i32 [[SUM2]], [[ONESIDED]]
+; CHECK-NEXT: [[SUM4:%.*]] = add i32 [[SUM3]], [[ONESIDED2]]
+; CHECK-NEXT: [[SUM5:%.*]] = add i32 [[SUM4]], [[REAL_SYNTH]]
+; CHECK-NEXT: [[SUM6:%.*]] = add i32 [[SUM5]], [[REAL_SYNTH2]]
+; CHECK-NEXT: [[SUM7:%.*]] = add i32 [[SUM6]], [[ODR]]
+; CHECK-NEXT: [[SUM8:%.*]] = add i32 [[SUM7]], [[ODR2]]
+; CHECK-NEXT: ret i32 [[SUM8]]
+;
+;
+; CHECK-LABEL: define linkonce_odr i32 @odr_b(
+; CHECK-SAME: i32 [[TMP0:%.*]]) !prof [[PROF18:![0-9]+]] {
+; CHECK-NEXT: [[TMP2:%.*]] = tail call i32 @[[GLOB0]](i32 [[TMP0]])
+; CHECK-NEXT: ret i32 [[TMP2]]
+;
+;
+; CHECK-LABEL: define linkonce_odr i32 @odr_a(
+; CHECK-SAME: i32 [[TMP0:%.*]]) !prof [[PROF18]] {
+; CHECK-NEXT: [[TMP2:%.*]] = tail call i32 @[[GLOB0]](i32 [[TMP0]])
+; CHECK-NEXT: ret i32 [[TMP2]]
+;
+;
+; ALIAS-LABEL: define internal i32 @basic_a(
+; ALIAS-SAME: i32 [[X:%.*]]) !prof [[PROF12:![0-9]+]] {
+; ALIAS-NEXT: [[ENTRY:.*:]]
+; ALIAS-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], 1
+; ALIAS-NEXT: ret i32 [[ADD]]
+;
+;
+; ALIAS-LABEL: define internal i32 @asym_a(
+; ALIAS-SAME: i32 [[X:%.*]]) !prof [[PROF13:![0-9]+]] {
+; ALIAS-NEXT: [[ENTRY:.*:]]
+; ALIAS-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], 2
+; ALIAS-NEXT: ret i32 [[ADD]]
+;
+;
+; ALIAS-LABEL: define internal i32 @onesided_a(
+; ALIAS-SAME: i32 [[X:%.*]]) !prof [[PROF14:![0-9]+]] {
+; ALIAS-NEXT: [[ENTRY:.*:]]
+; ALIAS-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], 3
+; ALIAS-NEXT: ret i32 [[ADD]]
+;
+;
+; ALIAS-LABEL: define internal i32 @real_synth_a(
+; ALIAS-SAME: i32 [[X:%.*]]) !prof [[PROF15:![0-9]+]] {
+; ALIAS-NEXT: [[ENTRY:.*:]]
+; ALIAS-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], 4
+; ALIAS-NEXT: ret i32 [[ADD]]
+;
+;
+; ALIAS-LABEL: define private i32 @0(
+; ALIAS-SAME: i32 [[X:%.*]]) !prof [[PROF12]] {
+; ALIAS-NEXT: [[ENTRY:.*:]]
+; ALIAS-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], 5
+; ALIAS-NEXT: ret i32 [[ADD]]
+;
+;
+; ALIAS-LABEL: define void @alias_a(
+; ALIAS-SAME: ) unnamed_addr !prof [[PROF16:![0-9]+]] {
+; ALIAS-NEXT: ret void
+;
+;
+; ALIAS-LABEL: define i32 @use_counts(
+; ALIAS-SAME: i32 [[X:%.*]]) {
+; ALIAS-NEXT: [[ENTRY:.*:]]
+; ALIAS-NEXT: [[BASIC:%.*]] = call i32 @basic_a(i32 [[X]])
+; ALIAS-NEXT: [[BASIC2:%.*]] = call i32 @basic_a(i32 [[X]])
+; ALIAS-NEXT: [[ASYM:%.*]] = call i32 @asym_a(i32 [[X]])
+; ALIAS-NEXT: [[ASYM2:%.*]] = call i32 @asym_a(i32 [[X]])
+; ALIAS-NEXT: [[ONESIDED:%.*]] = call i32 @onesided_a(i32 [[X]])
+; ALIAS-NEXT: [[ONESIDED2:%.*]] = call i32 @onesided_a(i32 [[X]])
+; ALIAS-NEXT: [[REAL_SYNTH:%.*]] = call i32 @real_synth_a(i32 [[X]])
+; ALIAS-NEXT: [[REAL_SYNTH2:%.*]] = call i32 @real_synth_a(i32 [[X]])
+; ALIAS-NEXT: [[ODR:%.*]] = call i32 @[[GLOB0:[0-9]+]](i32 [[X]])
+; ALIAS-NEXT: [[ODR2:%.*]] = call i32 @[[GLOB0]](i32 [[X]])
+; ALIAS-NEXT: call void @alias_a()
+; ALIAS-NEXT: call void @alias_a()
+; ALIAS-NEXT: [[SUM0:%.*]] = add i32 [[BASIC]], [[BASIC2]]
+; ALIAS-NEXT: [[SUM1:%.*]] = add i32 [[SUM0]], [[ASYM]]
+; ALIAS-NEXT: [[SUM2:%.*]] = add i32 [[SUM1]], [[ASYM2]]
+; ALIAS-NEXT: [[SUM3:%.*]] = add i32 [[SUM2]], [[ONESIDED]]
+; ALIAS-NEXT: [[SUM4:%.*]] = add i32 [[SUM3]], [[ONESIDED2]]
+; ALIAS-NEXT: [[SUM5:%.*]] = add i32 [[SUM4]], [[REAL_SYNTH]]
+; ALIAS-NEXT: [[SUM6:%.*]] = add i32 [[SUM5]], [[REAL_SYNTH2]]
+; ALIAS-NEXT: [[SUM7:%.*]] = add i32 [[SUM6]], [[ODR]]
+; ALIAS-NEXT: [[SUM8:%.*]] = add i32 [[SUM7]], [[ODR2]]
+; ALIAS-NEXT: ret i32 [[SUM8]]
+;
+;
+; ALIAS-LABEL: define linkonce_odr i32 @odr_b(
+; ALIAS-SAME: i32 [[TMP0:%.*]]) !prof [[PROF17:![0-9]+]] {
+; ALIAS-NEXT: [[TMP2:%.*]] = tail call i32 @[[GLOB0]](i32 [[TMP0]])
+; ALIAS-NEXT: ret i32 [[TMP2]]
+;
+;
+; ALIAS-LABEL: define linkonce_odr i32 @odr_a(
+; ALIAS-SAME: i32 [[TMP0:%.*]]) !prof [[PROF17]] {
+; ALIAS-NEXT: [[TMP2:%.*]] = tail call i32 @[[GLOB0]](i32 [[TMP0]])
+; ALIAS-NEXT: ret i32 [[TMP2]]
+;
+;.
+; CHECK: [[META0:![0-9]+]] = !{i32 1, !"ProfileSummary", [[META1:![0-9]+]]}
+; CHECK: [[META1]] = !{[[META2:![0-9]+]], [[META3:![0-9]+]], [[META4:![0-9]+]], [[META5:![0-9]+]], [[META6:![0-9]+]], [[META7:![0-9]+]], [[META8:![0-9]+]], [[META9:![0-9]+]]}
+; CHECK: [[META2]] = !{!"ProfileFormat", !"InstrProf"}
+; CHECK: [[META3]] = !{!"TotalCount", i64 3531}
+; CHECK: [[META4]] = !{!"MaxCount", i64 2000}
+; CHECK: [[META5]] = !{!"MaxInternalCount", i64 2000}
+; CHECK: [[META6]] = !{!"MaxFunctionCount", i64 2000}
+; CHECK: [[META7]] = !{!"NumCounts", i64 12}
+; CHECK: [[META8]] = !{!"NumFunctions", i64 12}
+; CHECK: [[META9]] = !{!"DetailedSummary", [[META10:![0-9]+]]}
+; CHECK: [[META10]] = !{[[META11:![0-9]+]]}
+; CHECK: [[META11]] = !{i32 10000, i64 1, i32 1}
+; CHECK: [[PROF12]] = !{!"function_entry_count", i64 2}
+; CHECK: [[PROF13]] = !{!"function_entry_count", i64 3000}
+; CHECK: [[PROF14]] = !{!"function_entry_count", i64 500}
+; CHECK: [[PROF15]] = !{!"synthetic_function_entry_count", i64 15}
+; CHECK: [[PROF16]] = !{!"function_entry_count", i64 7}
+; CHECK: [[PROF17]] = !{!"function_entry_count", i64 5}
+; CHECK: [[PROF18]] = !{!"function_entry_count", i64 1}
+;.
+; ALIAS: [[META0:![0-9]+]] = !{i32 1, !"ProfileSummary", [[META1:![0-9]+]]}
+; ALIAS: [[META1]] = !{[[META2:![0-9]+]], [[META3:![0-9]+]], [[META4:![0-9]+]], [[META5:![0-9]+]], [[META6:![0-9]+]], [[META7:![0-9]+]], [[META8:![0-9]+]], [[META9:![0-9]+]]}
+; ALIAS: [[META2]] = !{!"ProfileFormat", !"InstrProf"}
+; ALIAS: [[META3]] = !{!"TotalCount", i64 3531}
+; ALIAS: [[META4]] = !{!"MaxCount", i64 2000}
+; ALIAS: [[META5]] = !{!"MaxInternalCount", i64 2000}
+; ALIAS: [[META6]] = !{!"MaxFunctionCount", i64 2000}
+; ALIAS: [[META7]] = !{!"NumCounts", i64 12}
+; ALIAS: [[META8]] = !{!"NumFunctions", i64 12}
+; ALIAS: [[META9]] = !{!"DetailedSummary", [[META10:![0-9]+]]}
+; ALIAS: [[META10]] = !{[[META11:![0-9]+]]}
+; ALIAS: [[META11]] = !{i32 10000, i64 1, i32 1}
+; ALIAS: [[PROF12]] = !{!"function_entry_count", i64 2}
+; ALIAS: [[PROF13]] = !{!"function_entry_count", i64 3000}
+; ALIAS: [[PROF14]] = !{!"function_entry_count", i64 500}
+; ALIAS: [[PROF15]] = !{!"synthetic_function_entry_count", i64 15}
+; ALIAS: [[PROF16]] = !{!"function_entry_count", i64 12}
+; ALIAS: [[PROF17]] = !{!"function_entry_count", i64 1}
+;.
>From a24d3cebc91e3a49efa5cdfa99957da50b1fe61c Mon Sep 17 00:00:00 2001
From: Alok Kumar Sharma <AlokKumar.Sharma at amd.com>
Date: Tue, 23 Jun 2026 12:12:38 +0530
Subject: [PATCH 2/3] Addressed review.
---
llvm/lib/Transforms/IPO/MergeFunctions.cpp | 23 +-
.../merge-functions-entry-count-alias.ll | 51 +++
.../merge-functions-entry-count-no-alias.ll | 157 +++++++++
.../MergeFunc/merge-functions-entry-count.ll | 330 ------------------
4 files changed, 215 insertions(+), 346 deletions(-)
create mode 100644 llvm/test/Transforms/MergeFunc/merge-functions-entry-count-alias.ll
create mode 100644 llvm/test/Transforms/MergeFunc/merge-functions-entry-count-no-alias.ll
delete mode 100644 llvm/test/Transforms/MergeFunc/merge-functions-entry-count.ll
diff --git a/llvm/lib/Transforms/IPO/MergeFunctions.cpp b/llvm/lib/Transforms/IPO/MergeFunctions.cpp
index 8110653aac88e..703895cdd5b71 100644
--- a/llvm/lib/Transforms/IPO/MergeFunctions.cpp
+++ b/llvm/lib/Transforms/IPO/MergeFunctions.cpp
@@ -734,7 +734,7 @@ static void copyMetadataIfPresent(Function *From, Function *To,
// For better debugability, under MergeFunctionsPDI, we do not modify G's
// call sites to point to F even when within the same translation unit.
void MergeFunctions::writeThunk(Function *F, Function *G) {
- auto GEC = G->getEntryCount(/*AllowSynthetic=*/true);
+ std::optional<Function::ProfileCount> GEC = G->getEntryCount();
BasicBlock *GEntryBlock = nullptr;
std::vector<Instruction *> PDIUnrelatedWL;
std::vector<DbgVariableRecord *> PDVRUnrelatedWL;
@@ -886,21 +886,15 @@ static void mergeEntryCountsInto(Function *F,
return;
uint64_t Sum = SaturatingAdd(FC ? FC->getCount() : uint64_t{0},
GC ? GC->getCount() : uint64_t{0});
- Function::ProfileCountType PCT =
- ((FC && FC->isSynthetic()) || (GC && GC->isSynthetic()))
- ? Function::PCT_Synthetic
- : Function::PCT_Real;
- if (FC && FC->getType() != PCT) {
- F->setMetadata(LLVMContext::MD_prof, nullptr);
- F->setEntryCount(Function::ProfileCount(Sum, PCT));
- return;
- }
- F->setEntryCount(Sum, PCT);
+ F->setEntryCount(Sum);
}
// Merge two equivalent functions. Upon completion, Function G is deleted.
void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) {
+ std::optional<Function::ProfileCount> FEC = F->getEntryCount();
+ std::optional<Function::ProfileCount> GEC = G->getEntryCount();
+
// Create a new thunk that both F and G can call, if F cannot call G directly.
// That is the case if F is either interposable or if G is either weak_odr or
// linkonce_odr.
@@ -926,8 +920,6 @@ void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) {
// Ensure CFI type metadata is propagated to the new function.
copyMetadataIfPresent(F, NewF, "type");
copyMetadataIfPresent(F, NewF, "kcfi_type");
- auto FEC = F->getEntryCount(/*AllowSynthetic=*/true);
- auto GEC = G->getEntryCount(/*AllowSynthetic=*/true);
removeUsers(F);
F->replaceAllUsesWith(NewF);
@@ -953,13 +945,12 @@ void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) {
else
F->setAlignment(std::nullopt);
F->setLinkage(GlobalValue::PrivateLinkage);
+ // The private shared implementation accumulates both symbols' entries
+ // (FEC + GEC), while each ODR thunk retains its own per-symbol entry count.
mergeEntryCountsInto(F, FEC, GEC);
++NumDoubleWeak;
++NumFunctionsMerged;
} else {
- auto FEC = F->getEntryCount(/*AllowSynthetic=*/true);
- auto GEC = G->getEntryCount(/*AllowSynthetic=*/true);
-
// For better debugability, under MergeFunctionsPDI, we do not modify G's
// call sites to point to F even when within the same translation unit.
if (!G->isInterposable() && !MergeFunctionsPDI) {
diff --git a/llvm/test/Transforms/MergeFunc/merge-functions-entry-count-alias.ll b/llvm/test/Transforms/MergeFunc/merge-functions-entry-count-alias.ll
new file mode 100644
index 0000000000000..16e3717c034a8
--- /dev/null
+++ b/llvm/test/Transforms/MergeFunc/merge-functions-entry-count-alias.ll
@@ -0,0 +1,51 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=mergefunc -mergefunc-use-aliases < %s | FileCheck %s
+
+define void @alias_a() unnamed_addr !prof !12 {
+; CHECK-LABEL: define void @alias_a(
+; CHECK-SAME: ) unnamed_addr !prof [[PROF12:![0-9]+]] {
+; CHECK-NEXT: ret void
+;
+ ret void
+}
+
+define void @alias_b() unnamed_addr !prof !13 {
+ ret void
+}
+
+define i32 @use(i32 %x) {
+; CHECK-LABEL: define i32 @use(
+; CHECK-SAME: i32 [[X:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: call void @alias_a()
+; CHECK-NEXT: call void @alias_a()
+; CHECK-NEXT: ret i32 [[X]]
+;
+entry:
+ call void @alias_a()
+ call void @alias_b()
+ ret i32 %x
+}
+
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 1, !"ProfileSummary", !1}
+!1 = !{!2, !3, !4, !5, !6, !7, !8, !9}
+!2 = !{!"ProfileFormat", !"InstrProf"}
+!3 = !{!"TotalCount", i64 3531}
+!4 = !{!"MaxCount", i64 2000}
+!5 = !{!"MaxInternalCount", i64 2000}
+!6 = !{!"MaxFunctionCount", i64 2000}
+!7 = !{!"NumCounts", i64 12}
+!8 = !{!"NumFunctions", i64 12}
+!9 = !{!"DetailedSummary", !10}
+!10 = !{!11}
+!11 = !{i32 10000, i64 1, i32 1}
+!12 = !{!"function_entry_count", i64 7}
+!13 = !{!"function_entry_count", i64 5}
+;
+;
+;
+;.
+; CHECK: [[PROF12]] = !{!"function_entry_count", i64 12}
+;.
diff --git a/llvm/test/Transforms/MergeFunc/merge-functions-entry-count-no-alias.ll b/llvm/test/Transforms/MergeFunc/merge-functions-entry-count-no-alias.ll
new file mode 100644
index 0000000000000..a03e11a226060
--- /dev/null
+++ b/llvm/test/Transforms/MergeFunc/merge-functions-entry-count-no-alias.ll
@@ -0,0 +1,157 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
+; RUN: opt -S -passes=mergefunc < %s | FileCheck %s
+
+ at llvm.used = appending global [2 x ptr] [ptr @odr_a, ptr @odr_b], section "llvm.metadata"
+
+define internal i32 @basic_a(i32 %x) !prof !12 {
+entry:
+ %add = add nsw i32 %x, 1
+ ret i32 %add
+}
+
+define internal i32 @basic_b(i32 %x) !prof !12 {
+entry:
+ %add = add nsw i32 %x, 1
+ ret i32 %add
+}
+
+define internal i32 @asym_a(i32 %x) !prof !13 {
+entry:
+ %add = add nsw i32 %x, 2
+ ret i32 %add
+}
+
+define internal i32 @asym_b(i32 %x) !prof !14 {
+entry:
+ %add = add nsw i32 %x, 2
+ ret i32 %add
+}
+
+define internal i32 @onesided_a(i32 %x) {
+entry:
+ %add = add nsw i32 %x, 3
+ ret i32 %add
+}
+
+define internal i32 @onesided_b(i32 %x) !prof !15 {
+entry:
+ %add = add nsw i32 %x, 3
+ ret i32 %add
+}
+
+define linkonce_odr i32 @odr_a(i32 %x) !prof !12 {
+entry:
+ %add = add nsw i32 %x, 5
+ ret i32 %add
+}
+
+define linkonce_odr i32 @odr_b(i32 %x) !prof !12 {
+entry:
+ %add = add nsw i32 %x, 5
+ ret i32 %add
+}
+
+define i32 @use_counts(i32 %x) {
+entry:
+ %basic = call i32 @basic_a(i32 %x)
+ %basic2 = call i32 @basic_b(i32 %x)
+ %asym = call i32 @asym_a(i32 %x)
+ %asym2 = call i32 @asym_b(i32 %x)
+ %onesided = call i32 @onesided_a(i32 %x)
+ %onesided2 = call i32 @onesided_b(i32 %x)
+ %odr = call i32 @odr_a(i32 %x)
+ %odr2 = call i32 @odr_b(i32 %x)
+ %sum0 = add i32 %basic, %basic2
+ %sum1 = add i32 %sum0, %asym
+ %sum2 = add i32 %sum1, %asym2
+ %sum3 = add i32 %sum2, %onesided
+ %sum4 = add i32 %sum3, %onesided2
+ %sum5 = add i32 %sum4, %odr
+ %sum6 = add i32 %sum5, %odr2
+ ret i32 %sum6
+}
+
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 1, !"ProfileSummary", !1}
+!1 = !{!2, !3, !4, !5, !6, !7, !8, !9}
+!2 = !{!"ProfileFormat", !"InstrProf"}
+!3 = !{!"TotalCount", i64 3531}
+!4 = !{!"MaxCount", i64 2000}
+!5 = !{!"MaxInternalCount", i64 2000}
+!6 = !{!"MaxFunctionCount", i64 2000}
+!7 = !{!"NumCounts", i64 12}
+!8 = !{!"NumFunctions", i64 12}
+!9 = !{!"DetailedSummary", !10}
+!10 = !{!11}
+!11 = !{i32 10000, i64 1, i32 1}
+!12 = !{!"function_entry_count", i64 1}
+!13 = !{!"function_entry_count", i64 2000}
+!14 = !{!"function_entry_count", i64 1000}
+!15 = !{!"function_entry_count", i64 500}
+; CHECK-LABEL: define internal i32 @basic_a(
+; CHECK-SAME: i32 [[X:%.*]]) !prof [[PROF12:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], 1
+; CHECK-NEXT: ret i32 [[ADD]]
+;
+;
+; CHECK-LABEL: define internal i32 @asym_a(
+; CHECK-SAME: i32 [[X:%.*]]) !prof [[PROF13:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], 2
+; CHECK-NEXT: ret i32 [[ADD]]
+;
+;
+; CHECK-LABEL: define internal i32 @onesided_a(
+; CHECK-SAME: i32 [[X:%.*]]) !prof [[PROF14:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], 3
+; CHECK-NEXT: ret i32 [[ADD]]
+;
+;
+; CHECK-LABEL: define private i32 @0(
+; CHECK-SAME: i32 [[X:%.*]]) !prof [[PROF12]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], 5
+; CHECK-NEXT: ret i32 [[ADD]]
+;
+;
+; CHECK-LABEL: define i32 @use_counts(
+; CHECK-SAME: i32 [[X:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[BASIC:%.*]] = call i32 @basic_a(i32 [[X]])
+; CHECK-NEXT: [[BASIC2:%.*]] = call i32 @basic_a(i32 [[X]])
+; CHECK-NEXT: [[ASYM:%.*]] = call i32 @asym_a(i32 [[X]])
+; CHECK-NEXT: [[ASYM2:%.*]] = call i32 @asym_a(i32 [[X]])
+; CHECK-NEXT: [[ONESIDED:%.*]] = call i32 @onesided_a(i32 [[X]])
+; CHECK-NEXT: [[ONESIDED2:%.*]] = call i32 @onesided_a(i32 [[X]])
+; CHECK-NEXT: [[ODR:%.*]] = call i32 @[[GLOB0:[0-9]+]](i32 [[X]])
+; CHECK-NEXT: [[ODR2:%.*]] = call i32 @[[GLOB0]](i32 [[X]])
+; CHECK-NEXT: [[SUM0:%.*]] = add i32 [[BASIC]], [[BASIC2]]
+; CHECK-NEXT: [[SUM1:%.*]] = add i32 [[SUM0]], [[ASYM]]
+; CHECK-NEXT: [[SUM2:%.*]] = add i32 [[SUM1]], [[ASYM2]]
+; CHECK-NEXT: [[SUM3:%.*]] = add i32 [[SUM2]], [[ONESIDED]]
+; CHECK-NEXT: [[SUM4:%.*]] = add i32 [[SUM3]], [[ONESIDED2]]
+; CHECK-NEXT: [[SUM5:%.*]] = add i32 [[SUM4]], [[ODR]]
+; CHECK-NEXT: [[SUM6:%.*]] = add i32 [[SUM5]], [[ODR2]]
+; CHECK-NEXT: ret i32 [[SUM6]]
+;
+;
+; CHECK-LABEL: define linkonce_odr i32 @odr_b(
+; CHECK-SAME: i32 [[TMP0:%.*]]) !prof [[PROF15:![0-9]+]] {
+; CHECK-NEXT: [[TMP2:%.*]] = tail call i32 @[[GLOB0]](i32 [[TMP0]])
+; CHECK-NEXT: ret i32 [[TMP2]]
+;
+;
+; CHECK-LABEL: define linkonce_odr i32 @odr_a(
+; CHECK-SAME: i32 [[TMP0:%.*]]) !prof [[PROF15]] {
+; CHECK-NEXT: [[TMP2:%.*]] = tail call i32 @[[GLOB0]](i32 [[TMP0]])
+; CHECK-NEXT: ret i32 [[TMP2]]
+;
+;.
+; CHECK: [[PROF12]] = !{!"function_entry_count", i64 2}
+; CHECK: [[PROF13]] = !{!"function_entry_count", i64 3000}
+; CHECK: [[PROF14]] = !{!"function_entry_count", i64 500}
+; CHECK: [[PROF15]] = !{!"function_entry_count", i64 1}
+;.
diff --git a/llvm/test/Transforms/MergeFunc/merge-functions-entry-count.ll b/llvm/test/Transforms/MergeFunc/merge-functions-entry-count.ll
deleted file mode 100644
index 7bcab278b7055..0000000000000
--- a/llvm/test/Transforms/MergeFunc/merge-functions-entry-count.ll
+++ /dev/null
@@ -1,330 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --include-generated-funcs --version 5
-; RUN: opt -S -passes=mergefunc < %s | FileCheck %s
-; RUN: opt -S -passes=mergefunc -mergefunc-use-aliases < %s | FileCheck %s --check-prefix=ALIAS
-
-define internal i32 @basic_a(i32 %x) !prof !1 {
-entry:
- %add = add nsw i32 %x, 1
- ret i32 %add
-}
-
-define internal i32 @basic_b(i32 %x) !prof !1 {
-entry:
- %add = add nsw i32 %x, 1
- ret i32 %add
-}
-
-define internal i32 @asym_a(i32 %x) !prof !2 {
-entry:
- %add = add nsw i32 %x, 2
- ret i32 %add
-}
-
-define internal i32 @asym_b(i32 %x) !prof !3 {
-entry:
- %add = add nsw i32 %x, 2
- ret i32 %add
-}
-
-define internal i32 @onesided_a(i32 %x) {
-entry:
- %add = add nsw i32 %x, 3
- ret i32 %add
-}
-
-define internal i32 @onesided_b(i32 %x) !prof !4 {
-entry:
- %add = add nsw i32 %x, 3
- ret i32 %add
-}
-
-define internal i32 @real_synth_a(i32 %x) !prof !5 {
-entry:
- %add = add nsw i32 %x, 4
- ret i32 %add
-}
-
-define internal i32 @real_synth_b(i32 %x) !prof !6 {
-entry:
- %add = add nsw i32 %x, 4
- ret i32 %add
-}
-
-define linkonce_odr i32 @odr_a(i32 %x) !prof !1 {
-entry:
- %add = add nsw i32 %x, 5
- ret i32 %add
-}
-
-define linkonce_odr i32 @odr_b(i32 %x) !prof !1 {
-entry:
- %add = add nsw i32 %x, 5
- ret i32 %add
-}
-
- at llvm.used = appending global [2 x ptr] [ptr @odr_a, ptr @odr_b], section "llvm.metadata"
-
-define void @alias_a() unnamed_addr !prof !7 {
- ret void
-}
-
-define void @alias_b() unnamed_addr !prof !8 {
- ret void
-}
-
-define i32 @use_counts(i32 %x) {
-entry:
- %basic = call i32 @basic_a(i32 %x)
- %basic2 = call i32 @basic_b(i32 %x)
- %asym = call i32 @asym_a(i32 %x)
- %asym2 = call i32 @asym_b(i32 %x)
- %onesided = call i32 @onesided_a(i32 %x)
- %onesided2 = call i32 @onesided_b(i32 %x)
- %real_synth = call i32 @real_synth_a(i32 %x)
- %real_synth2 = call i32 @real_synth_b(i32 %x)
- %odr = call i32 @odr_a(i32 %x)
- %odr2 = call i32 @odr_b(i32 %x)
- call void @alias_a()
- call void @alias_b()
- %sum0 = add i32 %basic, %basic2
- %sum1 = add i32 %sum0, %asym
- %sum2 = add i32 %sum1, %asym2
- %sum3 = add i32 %sum2, %onesided
- %sum4 = add i32 %sum3, %onesided2
- %sum5 = add i32 %sum4, %real_synth
- %sum6 = add i32 %sum5, %real_synth2
- %sum7 = add i32 %sum6, %odr
- %sum8 = add i32 %sum7, %odr2
- ret i32 %sum8
-}
-
-!llvm.module.flags = !{!0}
-
-!0 = !{i32 1, !"ProfileSummary", !9}
-!1 = !{!"function_entry_count", i64 1}
-!2 = !{!"function_entry_count", i64 2000}
-!3 = !{!"function_entry_count", i64 1000}
-!4 = !{!"function_entry_count", i64 500}
-!5 = !{!"function_entry_count", i64 10}
-!6 = !{!"synthetic_function_entry_count", i64 5}
-!7 = !{!"function_entry_count", i64 7}
-!8 = !{!"function_entry_count", i64 5}
-!9 = !{!10, !11, !12, !13, !14, !15, !16, !17}
-!10 = !{!"ProfileFormat", !"InstrProf"}
-!11 = !{!"TotalCount", i64 3531}
-!12 = !{!"MaxCount", i64 2000}
-!13 = !{!"MaxInternalCount", i64 2000}
-!14 = !{!"MaxFunctionCount", i64 2000}
-!15 = !{!"NumCounts", i64 12}
-!16 = !{!"NumFunctions", i64 12}
-!17 = !{!"DetailedSummary", !18}
-!18 = !{!19}
-!19 = !{i32 10000, i64 1, i32 1}
-;.
-; CHECK: @llvm.used = appending global [2 x ptr] [ptr @odr_a, ptr @odr_b], section "llvm.metadata"
-;.
-; ALIAS: @llvm.used = appending global [2 x ptr] [ptr @odr_a, ptr @odr_b], section "llvm.metadata"
-; ALIAS: @alias_b = unnamed_addr alias void (), ptr @alias_a
-;.
-; CHECK-LABEL: define internal i32 @basic_a(
-; CHECK-SAME: i32 [[X:%.*]]) !prof [[PROF12:![0-9]+]] {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], 1
-; CHECK-NEXT: ret i32 [[ADD]]
-;
-;
-; CHECK-LABEL: define internal i32 @asym_a(
-; CHECK-SAME: i32 [[X:%.*]]) !prof [[PROF13:![0-9]+]] {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], 2
-; CHECK-NEXT: ret i32 [[ADD]]
-;
-;
-; CHECK-LABEL: define internal i32 @onesided_a(
-; CHECK-SAME: i32 [[X:%.*]]) !prof [[PROF14:![0-9]+]] {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], 3
-; CHECK-NEXT: ret i32 [[ADD]]
-;
-;
-; CHECK-LABEL: define internal i32 @real_synth_a(
-; CHECK-SAME: i32 [[X:%.*]]) !prof [[PROF15:![0-9]+]] {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], 4
-; CHECK-NEXT: ret i32 [[ADD]]
-;
-;
-; CHECK-LABEL: define private i32 @0(
-; CHECK-SAME: i32 [[X:%.*]]) !prof [[PROF12]] {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], 5
-; CHECK-NEXT: ret i32 [[ADD]]
-;
-;
-; CHECK-LABEL: define void @alias_a(
-; CHECK-SAME: ) unnamed_addr !prof [[PROF16:![0-9]+]] {
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define void @alias_b(
-; CHECK-SAME: ) unnamed_addr !prof [[PROF17:![0-9]+]] {
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define i32 @use_counts(
-; CHECK-SAME: i32 [[X:%.*]]) {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[BASIC:%.*]] = call i32 @basic_a(i32 [[X]])
-; CHECK-NEXT: [[BASIC2:%.*]] = call i32 @basic_a(i32 [[X]])
-; CHECK-NEXT: [[ASYM:%.*]] = call i32 @asym_a(i32 [[X]])
-; CHECK-NEXT: [[ASYM2:%.*]] = call i32 @asym_a(i32 [[X]])
-; CHECK-NEXT: [[ONESIDED:%.*]] = call i32 @onesided_a(i32 [[X]])
-; CHECK-NEXT: [[ONESIDED2:%.*]] = call i32 @onesided_a(i32 [[X]])
-; CHECK-NEXT: [[REAL_SYNTH:%.*]] = call i32 @real_synth_a(i32 [[X]])
-; CHECK-NEXT: [[REAL_SYNTH2:%.*]] = call i32 @real_synth_a(i32 [[X]])
-; CHECK-NEXT: [[ODR:%.*]] = call i32 @[[GLOB0:[0-9]+]](i32 [[X]])
-; CHECK-NEXT: [[ODR2:%.*]] = call i32 @[[GLOB0]](i32 [[X]])
-; CHECK-NEXT: call void @alias_a()
-; CHECK-NEXT: call void @alias_a()
-; CHECK-NEXT: [[SUM0:%.*]] = add i32 [[BASIC]], [[BASIC2]]
-; CHECK-NEXT: [[SUM1:%.*]] = add i32 [[SUM0]], [[ASYM]]
-; CHECK-NEXT: [[SUM2:%.*]] = add i32 [[SUM1]], [[ASYM2]]
-; CHECK-NEXT: [[SUM3:%.*]] = add i32 [[SUM2]], [[ONESIDED]]
-; CHECK-NEXT: [[SUM4:%.*]] = add i32 [[SUM3]], [[ONESIDED2]]
-; CHECK-NEXT: [[SUM5:%.*]] = add i32 [[SUM4]], [[REAL_SYNTH]]
-; CHECK-NEXT: [[SUM6:%.*]] = add i32 [[SUM5]], [[REAL_SYNTH2]]
-; CHECK-NEXT: [[SUM7:%.*]] = add i32 [[SUM6]], [[ODR]]
-; CHECK-NEXT: [[SUM8:%.*]] = add i32 [[SUM7]], [[ODR2]]
-; CHECK-NEXT: ret i32 [[SUM8]]
-;
-;
-; CHECK-LABEL: define linkonce_odr i32 @odr_b(
-; CHECK-SAME: i32 [[TMP0:%.*]]) !prof [[PROF18:![0-9]+]] {
-; CHECK-NEXT: [[TMP2:%.*]] = tail call i32 @[[GLOB0]](i32 [[TMP0]])
-; CHECK-NEXT: ret i32 [[TMP2]]
-;
-;
-; CHECK-LABEL: define linkonce_odr i32 @odr_a(
-; CHECK-SAME: i32 [[TMP0:%.*]]) !prof [[PROF18]] {
-; CHECK-NEXT: [[TMP2:%.*]] = tail call i32 @[[GLOB0]](i32 [[TMP0]])
-; CHECK-NEXT: ret i32 [[TMP2]]
-;
-;
-; ALIAS-LABEL: define internal i32 @basic_a(
-; ALIAS-SAME: i32 [[X:%.*]]) !prof [[PROF12:![0-9]+]] {
-; ALIAS-NEXT: [[ENTRY:.*:]]
-; ALIAS-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], 1
-; ALIAS-NEXT: ret i32 [[ADD]]
-;
-;
-; ALIAS-LABEL: define internal i32 @asym_a(
-; ALIAS-SAME: i32 [[X:%.*]]) !prof [[PROF13:![0-9]+]] {
-; ALIAS-NEXT: [[ENTRY:.*:]]
-; ALIAS-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], 2
-; ALIAS-NEXT: ret i32 [[ADD]]
-;
-;
-; ALIAS-LABEL: define internal i32 @onesided_a(
-; ALIAS-SAME: i32 [[X:%.*]]) !prof [[PROF14:![0-9]+]] {
-; ALIAS-NEXT: [[ENTRY:.*:]]
-; ALIAS-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], 3
-; ALIAS-NEXT: ret i32 [[ADD]]
-;
-;
-; ALIAS-LABEL: define internal i32 @real_synth_a(
-; ALIAS-SAME: i32 [[X:%.*]]) !prof [[PROF15:![0-9]+]] {
-; ALIAS-NEXT: [[ENTRY:.*:]]
-; ALIAS-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], 4
-; ALIAS-NEXT: ret i32 [[ADD]]
-;
-;
-; ALIAS-LABEL: define private i32 @0(
-; ALIAS-SAME: i32 [[X:%.*]]) !prof [[PROF12]] {
-; ALIAS-NEXT: [[ENTRY:.*:]]
-; ALIAS-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], 5
-; ALIAS-NEXT: ret i32 [[ADD]]
-;
-;
-; ALIAS-LABEL: define void @alias_a(
-; ALIAS-SAME: ) unnamed_addr !prof [[PROF16:![0-9]+]] {
-; ALIAS-NEXT: ret void
-;
-;
-; ALIAS-LABEL: define i32 @use_counts(
-; ALIAS-SAME: i32 [[X:%.*]]) {
-; ALIAS-NEXT: [[ENTRY:.*:]]
-; ALIAS-NEXT: [[BASIC:%.*]] = call i32 @basic_a(i32 [[X]])
-; ALIAS-NEXT: [[BASIC2:%.*]] = call i32 @basic_a(i32 [[X]])
-; ALIAS-NEXT: [[ASYM:%.*]] = call i32 @asym_a(i32 [[X]])
-; ALIAS-NEXT: [[ASYM2:%.*]] = call i32 @asym_a(i32 [[X]])
-; ALIAS-NEXT: [[ONESIDED:%.*]] = call i32 @onesided_a(i32 [[X]])
-; ALIAS-NEXT: [[ONESIDED2:%.*]] = call i32 @onesided_a(i32 [[X]])
-; ALIAS-NEXT: [[REAL_SYNTH:%.*]] = call i32 @real_synth_a(i32 [[X]])
-; ALIAS-NEXT: [[REAL_SYNTH2:%.*]] = call i32 @real_synth_a(i32 [[X]])
-; ALIAS-NEXT: [[ODR:%.*]] = call i32 @[[GLOB0:[0-9]+]](i32 [[X]])
-; ALIAS-NEXT: [[ODR2:%.*]] = call i32 @[[GLOB0]](i32 [[X]])
-; ALIAS-NEXT: call void @alias_a()
-; ALIAS-NEXT: call void @alias_a()
-; ALIAS-NEXT: [[SUM0:%.*]] = add i32 [[BASIC]], [[BASIC2]]
-; ALIAS-NEXT: [[SUM1:%.*]] = add i32 [[SUM0]], [[ASYM]]
-; ALIAS-NEXT: [[SUM2:%.*]] = add i32 [[SUM1]], [[ASYM2]]
-; ALIAS-NEXT: [[SUM3:%.*]] = add i32 [[SUM2]], [[ONESIDED]]
-; ALIAS-NEXT: [[SUM4:%.*]] = add i32 [[SUM3]], [[ONESIDED2]]
-; ALIAS-NEXT: [[SUM5:%.*]] = add i32 [[SUM4]], [[REAL_SYNTH]]
-; ALIAS-NEXT: [[SUM6:%.*]] = add i32 [[SUM5]], [[REAL_SYNTH2]]
-; ALIAS-NEXT: [[SUM7:%.*]] = add i32 [[SUM6]], [[ODR]]
-; ALIAS-NEXT: [[SUM8:%.*]] = add i32 [[SUM7]], [[ODR2]]
-; ALIAS-NEXT: ret i32 [[SUM8]]
-;
-;
-; ALIAS-LABEL: define linkonce_odr i32 @odr_b(
-; ALIAS-SAME: i32 [[TMP0:%.*]]) !prof [[PROF17:![0-9]+]] {
-; ALIAS-NEXT: [[TMP2:%.*]] = tail call i32 @[[GLOB0]](i32 [[TMP0]])
-; ALIAS-NEXT: ret i32 [[TMP2]]
-;
-;
-; ALIAS-LABEL: define linkonce_odr i32 @odr_a(
-; ALIAS-SAME: i32 [[TMP0:%.*]]) !prof [[PROF17]] {
-; ALIAS-NEXT: [[TMP2:%.*]] = tail call i32 @[[GLOB0]](i32 [[TMP0]])
-; ALIAS-NEXT: ret i32 [[TMP2]]
-;
-;.
-; CHECK: [[META0:![0-9]+]] = !{i32 1, !"ProfileSummary", [[META1:![0-9]+]]}
-; CHECK: [[META1]] = !{[[META2:![0-9]+]], [[META3:![0-9]+]], [[META4:![0-9]+]], [[META5:![0-9]+]], [[META6:![0-9]+]], [[META7:![0-9]+]], [[META8:![0-9]+]], [[META9:![0-9]+]]}
-; CHECK: [[META2]] = !{!"ProfileFormat", !"InstrProf"}
-; CHECK: [[META3]] = !{!"TotalCount", i64 3531}
-; CHECK: [[META4]] = !{!"MaxCount", i64 2000}
-; CHECK: [[META5]] = !{!"MaxInternalCount", i64 2000}
-; CHECK: [[META6]] = !{!"MaxFunctionCount", i64 2000}
-; CHECK: [[META7]] = !{!"NumCounts", i64 12}
-; CHECK: [[META8]] = !{!"NumFunctions", i64 12}
-; CHECK: [[META9]] = !{!"DetailedSummary", [[META10:![0-9]+]]}
-; CHECK: [[META10]] = !{[[META11:![0-9]+]]}
-; CHECK: [[META11]] = !{i32 10000, i64 1, i32 1}
-; CHECK: [[PROF12]] = !{!"function_entry_count", i64 2}
-; CHECK: [[PROF13]] = !{!"function_entry_count", i64 3000}
-; CHECK: [[PROF14]] = !{!"function_entry_count", i64 500}
-; CHECK: [[PROF15]] = !{!"synthetic_function_entry_count", i64 15}
-; CHECK: [[PROF16]] = !{!"function_entry_count", i64 7}
-; CHECK: [[PROF17]] = !{!"function_entry_count", i64 5}
-; CHECK: [[PROF18]] = !{!"function_entry_count", i64 1}
-;.
-; ALIAS: [[META0:![0-9]+]] = !{i32 1, !"ProfileSummary", [[META1:![0-9]+]]}
-; ALIAS: [[META1]] = !{[[META2:![0-9]+]], [[META3:![0-9]+]], [[META4:![0-9]+]], [[META5:![0-9]+]], [[META6:![0-9]+]], [[META7:![0-9]+]], [[META8:![0-9]+]], [[META9:![0-9]+]]}
-; ALIAS: [[META2]] = !{!"ProfileFormat", !"InstrProf"}
-; ALIAS: [[META3]] = !{!"TotalCount", i64 3531}
-; ALIAS: [[META4]] = !{!"MaxCount", i64 2000}
-; ALIAS: [[META5]] = !{!"MaxInternalCount", i64 2000}
-; ALIAS: [[META6]] = !{!"MaxFunctionCount", i64 2000}
-; ALIAS: [[META7]] = !{!"NumCounts", i64 12}
-; ALIAS: [[META8]] = !{!"NumFunctions", i64 12}
-; ALIAS: [[META9]] = !{!"DetailedSummary", [[META10:![0-9]+]]}
-; ALIAS: [[META10]] = !{[[META11:![0-9]+]]}
-; ALIAS: [[META11]] = !{i32 10000, i64 1, i32 1}
-; ALIAS: [[PROF12]] = !{!"function_entry_count", i64 2}
-; ALIAS: [[PROF13]] = !{!"function_entry_count", i64 3000}
-; ALIAS: [[PROF14]] = !{!"function_entry_count", i64 500}
-; ALIAS: [[PROF15]] = !{!"synthetic_function_entry_count", i64 15}
-; ALIAS: [[PROF16]] = !{!"function_entry_count", i64 12}
-; ALIAS: [[PROF17]] = !{!"function_entry_count", i64 1}
-;.
>From f1a8e123a6244e6c0556b7586344a58534a13349 Mon Sep 17 00:00:00 2001
From: Alok Kumar Sharma <AlokKumar.Sharma at amd.com>
Date: Tue, 30 Jun 2026 11:04:58 +0530
Subject: [PATCH 3/3] Fixed build failure on rebase caused due to API change.
---
llvm/lib/Transforms/IPO/MergeFunctions.cpp | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Transforms/IPO/MergeFunctions.cpp b/llvm/lib/Transforms/IPO/MergeFunctions.cpp
index 703895cdd5b71..d407511880a99 100644
--- a/llvm/lib/Transforms/IPO/MergeFunctions.cpp
+++ b/llvm/lib/Transforms/IPO/MergeFunctions.cpp
@@ -734,7 +734,7 @@ static void copyMetadataIfPresent(Function *From, Function *To,
// For better debugability, under MergeFunctionsPDI, we do not modify G's
// call sites to point to F even when within the same translation unit.
void MergeFunctions::writeThunk(Function *F, Function *G) {
- std::optional<Function::ProfileCount> GEC = G->getEntryCount();
+ std::optional<uint64_t> GEC = G->getEntryCount();
BasicBlock *GEntryBlock = nullptr;
std::vector<Instruction *> PDIUnrelatedWL;
std::vector<DbgVariableRecord *> PDVRUnrelatedWL;
@@ -879,21 +879,19 @@ static bool isODR(const Function *F) {
return F->hasWeakODRLinkage() || F->hasLinkOnceODRLinkage();
}
-static void mergeEntryCountsInto(Function *F,
- std::optional<Function::ProfileCount> FC,
- std::optional<Function::ProfileCount> GC) {
+static void mergeEntryCountsInto(Function *F, std::optional<uint64_t> FC,
+ std::optional<uint64_t> GC) {
if (!FC && !GC)
return;
- uint64_t Sum = SaturatingAdd(FC ? FC->getCount() : uint64_t{0},
- GC ? GC->getCount() : uint64_t{0});
+ uint64_t Sum = SaturatingAdd(FC ? *FC : uint64_t{0}, GC ? *GC : uint64_t{0});
F->setEntryCount(Sum);
}
// Merge two equivalent functions. Upon completion, Function G is deleted.
void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) {
- std::optional<Function::ProfileCount> FEC = F->getEntryCount();
- std::optional<Function::ProfileCount> GEC = G->getEntryCount();
+ std::optional<uint64_t> FEC = F->getEntryCount();
+ std::optional<uint64_t> GEC = G->getEntryCount();
// Create a new thunk that both F and G can call, if F cannot call G directly.
// That is the case if F is either interposable or if G is either weak_odr or
More information about the llvm-commits
mailing list