[llvm] [Metadata][profcheck] Handle identical MDNodes in getMergedProfMetadata (PR #175701)
Snehasish Kumar via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 14 10:46:12 PST 2026
https://github.com/snehasish updated https://github.com/llvm/llvm-project/pull/175701
>From a068116f0a35fec5793b945d979920f465ca982a Mon Sep 17 00:00:00 2001
From: Snehasish Kumar <snehasishk at google.com>
Date: Tue, 13 Jan 2026 02:40:51 +0000
Subject: [PATCH 1/7] [Metadata][profcheck] Handle identical MDNodes in
getMergedProfMetadata
This fixes a bug where !prof metadata was dropped from SelectInsts when GVN simplified/merged them.
Guarded by -profcheck-disable-metadata-fixes. Exposed by the tests in
Transforms/SampleProfile.
---
llvm/lib/IR/Metadata.cpp | 12 +++++++
llvm/unittests/IR/MetadataTest.cpp | 50 ++++++++++++++++++++++++++++++
2 files changed, 62 insertions(+)
diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp
index 1add0c7930bc9..f5009b212856d 100644
--- a/llvm/lib/IR/Metadata.cpp
+++ b/llvm/lib/IR/Metadata.cpp
@@ -46,6 +46,8 @@
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/CommandLine.h"
+
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/ModRef.h"
@@ -58,6 +60,10 @@
using namespace llvm;
+namespace llvm {
+extern cl::opt<bool> ProfcheckDisableMetadataFixes;
+}
+
MetadataAsValue::MetadataAsValue(Type *Ty, Metadata *MD)
: Value(Ty, MetadataAsValueVal), MD(MD) {
track();
@@ -1242,6 +1248,12 @@ MDNode *MDNode::getMergedProfMetadata(MDNode *A, MDNode *B,
return A ? A : B;
}
+ if (A == B && !ProfcheckDisableMetadataFixes) {
+ // For calls, we want to sum the weights even if identical.
+ if (!isa<CallInst>(AInstr))
+ return A;
+ }
+
assert(AInstr->getMetadata(LLVMContext::MD_prof) == A &&
"Caller should guarantee");
assert(BInstr->getMetadata(LLVMContext::MD_prof) == B &&
diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index 85c79d13ae7ce..24e8b47b7af34 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -5463,6 +5463,56 @@ TEST_F(MDTupleAllocationTest, Tracking2) {
EXPECT_EQ(A->getOperand(2), Value2);
}
+TEST_F(MDNodeTest, MergedProfMetadata) {
+ // Check that identical profile metadata is merged correctly.
+ Metadata *Ops[] = {
+ ConstantAsMetadata::get(ConstantInt::get(Context, APInt(32, 1))),
+ ConstantAsMetadata::get(ConstantInt::get(Context, APInt(32, 10))),
+ ConstantAsMetadata::get(ConstantInt::get(Context, APInt(32, 20)))};
+ MDNode *Prof = MDNode::get(Context, Ops);
+
+ // Create instructions to pass to getMergedProfMetadata.
+ // It requires the instructions to be of a supported type (e.g., SelectInst).
+ Value *C = ConstantInt::get(Context, APInt(1, 1));
+ Value *V1 = ConstantInt::get(Context, APInt(32, 1));
+ Value *V2 = ConstantInt::get(Context, APInt(32, 2));
+ std::unique_ptr<SelectInst> SI1(SelectInst::Create(C, V1, V2));
+ std::unique_ptr<SelectInst> SI2(SelectInst::Create(C, V1, V2));
+
+ SI1->setMetadata(LLVMContext::MD_prof, Prof);
+ SI2->setMetadata(LLVMContext::MD_prof, Prof);
+
+ MDNode *Merged =
+ MDNode::getMergedProfMetadata(Prof, Prof, SI1.get(), SI2.get());
+ EXPECT_EQ(Merged, Prof);
+}
+
+TEST_F(MDNodeTest, MergedProfMetadata_CallInst) {
+ // Check that identical profile metadata on CallInsts is SUMMED, not preserved.
+ Metadata *Ops[] = {
+ MDString::get(Context, "branch_weights"),
+ ConstantAsMetadata::get(ConstantInt::get(Context, APInt(32, 10)))};
+ MDNode *Prof = MDNode::get(Context, Ops);
+
+ // Create two CallInsts.
+ FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context), false);
+ std::unique_ptr<CallInst> CI1(CallInst::Create(FTy, getFunction("f"), ArrayRef<Value *>()));
+ std::unique_ptr<CallInst> CI2(CallInst::Create(FTy, getFunction("f"), ArrayRef<Value *>()));
+
+ CI1->setMetadata(LLVMContext::MD_prof, Prof);
+ CI2->setMetadata(LLVMContext::MD_prof, Prof);
+
+ MDNode *Merged =
+ MDNode::getMergedProfMetadata(Prof, Prof, CI1.get(), CI2.get());
+
+ // Expect merged node to be different (summed weights).
+ EXPECT_NE(Merged, Prof);
+ // Verify value is 20.
+ ASSERT_EQ(Merged->getNumOperands(), 2u);
+ ConstantInt *W = mdconst::extract<ConstantInt>(Merged->getOperand(1));
+ EXPECT_EQ(W->getZExtValue(), 20u);
+}
+
#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG) && !defined(GTEST_HAS_SEH)
typedef MetadataTest MDTupleAllocationDeathTest;
TEST_F(MDTupleAllocationDeathTest, ResizeRejected) {
>From 01ec841118db22aeb20c014815b966bb2e0abdd7 Mon Sep 17 00:00:00 2001
From: Snehasish Kumar <snehasishk at google.com>
Date: Tue, 13 Jan 2026 04:11:53 +0000
Subject: [PATCH 2/7] Move the check after merging for calls to simplify the
condition
---
llvm/lib/IR/Metadata.cpp | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp
index f5009b212856d..326abd87ddae9 100644
--- a/llvm/lib/IR/Metadata.cpp
+++ b/llvm/lib/IR/Metadata.cpp
@@ -1248,12 +1248,6 @@ MDNode *MDNode::getMergedProfMetadata(MDNode *A, MDNode *B,
return A ? A : B;
}
- if (A == B && !ProfcheckDisableMetadataFixes) {
- // For calls, we want to sum the weights even if identical.
- if (!isa<CallInst>(AInstr))
- return A;
- }
-
assert(AInstr->getMetadata(LLVMContext::MD_prof) == A &&
"Caller should guarantee");
assert(BInstr->getMetadata(LLVMContext::MD_prof) == B &&
@@ -1267,6 +1261,9 @@ MDNode *MDNode::getMergedProfMetadata(MDNode *A, MDNode *B,
BCall->getCalledFunction())
return mergeDirectCallProfMetadata(A, B, AInstr, BInstr);
+ if (A == B && !ProfcheckDisableMetadataFixes)
+ return A;
+
// The rest of the cases are not implemented but could be added
// when there are use cases.
return nullptr;
>From 2192484a349c0d41c8f72117d7e7ec8772656e3e Mon Sep 17 00:00:00 2001
From: Snehasish Kumar <snehasishk at google.com>
Date: Tue, 13 Jan 2026 04:14:06 +0000
Subject: [PATCH 3/7] Drop the summation unittest since it's already covered by
the gvn lit tests
---
llvm/unittests/IR/MetadataTest.cpp | 26 --------------------------
1 file changed, 26 deletions(-)
diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index 24e8b47b7af34..edf28a9503fe2 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -5487,32 +5487,6 @@ TEST_F(MDNodeTest, MergedProfMetadata) {
EXPECT_EQ(Merged, Prof);
}
-TEST_F(MDNodeTest, MergedProfMetadata_CallInst) {
- // Check that identical profile metadata on CallInsts is SUMMED, not preserved.
- Metadata *Ops[] = {
- MDString::get(Context, "branch_weights"),
- ConstantAsMetadata::get(ConstantInt::get(Context, APInt(32, 10)))};
- MDNode *Prof = MDNode::get(Context, Ops);
-
- // Create two CallInsts.
- FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context), false);
- std::unique_ptr<CallInst> CI1(CallInst::Create(FTy, getFunction("f"), ArrayRef<Value *>()));
- std::unique_ptr<CallInst> CI2(CallInst::Create(FTy, getFunction("f"), ArrayRef<Value *>()));
-
- CI1->setMetadata(LLVMContext::MD_prof, Prof);
- CI2->setMetadata(LLVMContext::MD_prof, Prof);
-
- MDNode *Merged =
- MDNode::getMergedProfMetadata(Prof, Prof, CI1.get(), CI2.get());
-
- // Expect merged node to be different (summed weights).
- EXPECT_NE(Merged, Prof);
- // Verify value is 20.
- ASSERT_EQ(Merged->getNumOperands(), 2u);
- ConstantInt *W = mdconst::extract<ConstantInt>(Merged->getOperand(1));
- EXPECT_EQ(W->getZExtValue(), 20u);
-}
-
#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG) && !defined(GTEST_HAS_SEH)
typedef MetadataTest MDTupleAllocationDeathTest;
TEST_F(MDTupleAllocationDeathTest, ResizeRejected) {
>From e0427360baa645b4cf7e56744ba53040f328e29c Mon Sep 17 00:00:00 2001
From: Snehasish Kumar <snehasishk at google.com>
Date: Tue, 13 Jan 2026 05:37:22 +0000
Subject: [PATCH 4/7] Revert "Drop the summation unittest since it's already
covered by the gvn lit tests"
This reverts commit fb0d7df21794ab50eaab4cb6e249679089a5a501.
---
llvm/unittests/IR/MetadataTest.cpp | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index edf28a9503fe2..24e8b47b7af34 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -5487,6 +5487,32 @@ TEST_F(MDNodeTest, MergedProfMetadata) {
EXPECT_EQ(Merged, Prof);
}
+TEST_F(MDNodeTest, MergedProfMetadata_CallInst) {
+ // Check that identical profile metadata on CallInsts is SUMMED, not preserved.
+ Metadata *Ops[] = {
+ MDString::get(Context, "branch_weights"),
+ ConstantAsMetadata::get(ConstantInt::get(Context, APInt(32, 10)))};
+ MDNode *Prof = MDNode::get(Context, Ops);
+
+ // Create two CallInsts.
+ FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context), false);
+ std::unique_ptr<CallInst> CI1(CallInst::Create(FTy, getFunction("f"), ArrayRef<Value *>()));
+ std::unique_ptr<CallInst> CI2(CallInst::Create(FTy, getFunction("f"), ArrayRef<Value *>()));
+
+ CI1->setMetadata(LLVMContext::MD_prof, Prof);
+ CI2->setMetadata(LLVMContext::MD_prof, Prof);
+
+ MDNode *Merged =
+ MDNode::getMergedProfMetadata(Prof, Prof, CI1.get(), CI2.get());
+
+ // Expect merged node to be different (summed weights).
+ EXPECT_NE(Merged, Prof);
+ // Verify value is 20.
+ ASSERT_EQ(Merged->getNumOperands(), 2u);
+ ConstantInt *W = mdconst::extract<ConstantInt>(Merged->getOperand(1));
+ EXPECT_EQ(W->getZExtValue(), 20u);
+}
+
#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG) && !defined(GTEST_HAS_SEH)
typedef MetadataTest MDTupleAllocationDeathTest;
TEST_F(MDTupleAllocationDeathTest, ResizeRejected) {
>From 13dd5df83370a4e06864f3512d37ba592005c54d Mon Sep 17 00:00:00 2001
From: Snehasish Kumar <snehasishk at google.com>
Date: Tue, 13 Jan 2026 06:01:40 +0000
Subject: [PATCH 5/7] clang format
---
llvm/unittests/IR/MetadataTest.cpp | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index 24e8b47b7af34..5b4935f8ba88f 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -5488,7 +5488,8 @@ TEST_F(MDNodeTest, MergedProfMetadata) {
}
TEST_F(MDNodeTest, MergedProfMetadata_CallInst) {
- // Check that identical profile metadata on CallInsts is SUMMED, not preserved.
+ // Check that identical profile metadata on CallInsts is SUMMED, not
+ // preserved.
Metadata *Ops[] = {
MDString::get(Context, "branch_weights"),
ConstantAsMetadata::get(ConstantInt::get(Context, APInt(32, 10)))};
@@ -5496,8 +5497,10 @@ TEST_F(MDNodeTest, MergedProfMetadata_CallInst) {
// Create two CallInsts.
FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context), false);
- std::unique_ptr<CallInst> CI1(CallInst::Create(FTy, getFunction("f"), ArrayRef<Value *>()));
- std::unique_ptr<CallInst> CI2(CallInst::Create(FTy, getFunction("f"), ArrayRef<Value *>()));
+ std::unique_ptr<CallInst> CI1(
+ CallInst::Create(FTy, getFunction("f"), ArrayRef<Value *>()));
+ std::unique_ptr<CallInst> CI2(
+ CallInst::Create(FTy, getFunction("f"), ArrayRef<Value *>()));
CI1->setMetadata(LLVMContext::MD_prof, Prof);
CI2->setMetadata(LLVMContext::MD_prof, Prof);
>From 923144c59651263e8c3a0491b3a8887d66eee5b1 Mon Sep 17 00:00:00 2001
From: Snehasish Kumar <snehasishk at google.com>
Date: Wed, 14 Jan 2026 06:55:24 +0000
Subject: [PATCH 6/7] Update profcheck-xfail.txt
---
llvm/utils/profcheck-xfail.txt | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/llvm/utils/profcheck-xfail.txt b/llvm/utils/profcheck-xfail.txt
index 564fbf3d00a48..d42d58d17cc94 100644
--- a/llvm/utils/profcheck-xfail.txt
+++ b/llvm/utils/profcheck-xfail.txt
@@ -505,8 +505,9 @@ Transforms/PreISelIntrinsicLowering/AArch64/expand-exp.ll
Transforms/PreISelIntrinsicLowering/AArch64/expand-log.ll
Transforms/PreISelIntrinsicLowering/PowerPC/memset-pattern.ll
Transforms/PreISelIntrinsicLowering/RISCV/memset-pattern.ll
-Transforms/SampleProfile/pseudo-probe-profile-mismatch-thinlto.ll
-Transforms/SampleProfile/remarks-hotness.ll
+Transforms/PreISelIntrinsicLowering/X86/memcpy-inline-non-constant-len.ll
+Transforms/PreISelIntrinsicLowering/X86/memset-inline-non-constant-len.ll
+Transforms/PreISelIntrinsicLowering/X86/memset-pattern.ll
Transforms/ScalarizeMaskedMemIntrin/AArch64/expand-masked-load.ll
Transforms/ScalarizeMaskedMemIntrin/AArch64/expand-masked-store.ll
Transforms/ScalarizeMaskedMemIntrin/AArch64/streaming-compatible-expand-masked-gather-scatter.ll
>From d87e81e91d1a20bf4c99e0a3abf9790a58ed1bdf Mon Sep 17 00:00:00 2001
From: Snehasish Kumar <snehasishk at google.com>
Date: Wed, 14 Jan 2026 18:45:24 +0000
Subject: [PATCH 7/7] fix bad merge
---
llvm/utils/profcheck-xfail.txt | 3 ---
1 file changed, 3 deletions(-)
diff --git a/llvm/utils/profcheck-xfail.txt b/llvm/utils/profcheck-xfail.txt
index d42d58d17cc94..3a1a26dfd8840 100644
--- a/llvm/utils/profcheck-xfail.txt
+++ b/llvm/utils/profcheck-xfail.txt
@@ -505,9 +505,6 @@ Transforms/PreISelIntrinsicLowering/AArch64/expand-exp.ll
Transforms/PreISelIntrinsicLowering/AArch64/expand-log.ll
Transforms/PreISelIntrinsicLowering/PowerPC/memset-pattern.ll
Transforms/PreISelIntrinsicLowering/RISCV/memset-pattern.ll
-Transforms/PreISelIntrinsicLowering/X86/memcpy-inline-non-constant-len.ll
-Transforms/PreISelIntrinsicLowering/X86/memset-inline-non-constant-len.ll
-Transforms/PreISelIntrinsicLowering/X86/memset-pattern.ll
Transforms/ScalarizeMaskedMemIntrin/AArch64/expand-masked-load.ll
Transforms/ScalarizeMaskedMemIntrin/AArch64/expand-masked-store.ll
Transforms/ScalarizeMaskedMemIntrin/AArch64/streaming-compatible-expand-masked-gather-scatter.ll
More information about the llvm-commits
mailing list