diff --git a/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp b/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp --- a/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp +++ b/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp @@ -1245,6 +1245,28 @@ llvm_unreachable("Cannot find the unknown count edge"); } +// Emit function metadata indicating PGO profile mismatch. +static void annotateFunctionWithHashMismatch(Function &F, + LLVMContext &ctx) { + const char MetadataName[] = "instr_prof_hash_mismatch"; + SmallVector Names; + // If this metadata already exists, ignore. + auto *Existing = F.getMetadata(LLVMContext::MD_annotation); + if (Existing) { + MDTuple *Tuple = cast(Existing); + for (auto &N : Tuple->operands()) { + if (cast(N.get())->getString() == MetadataName) + return; + Names.push_back(N.get()); + } + } + + MDBuilder MDB(ctx); + Names.push_back(MDB.createString(MetadataName)); + MDNode *MD = MDTuple::get(ctx, Names); + F.setMetadata(LLVMContext::MD_annotation, MD); +} + // Read the profile from ProfileFileName and assign the value to the // instrumented BB and the edges. This function also updates ProgramMaxCount. // Return true if the profile are successfully read, and false on errors. @@ -1272,6 +1294,8 @@ (F.hasComdat() || F.getLinkage() == GlobalValue::AvailableExternallyLinkage)); LLVM_DEBUG(dbgs() << "hash mismatch (skip=" << SkipWarning << ")"); + // Emit function metadata indicating PGO profile mismatch. + annotateFunctionWithHashMismatch(F, M->getContext()); } LLVM_DEBUG(dbgs() << " IsCS=" << IsCS << "\n"); diff --git a/llvm/test/Transforms/PGOProfile/Inputs/hash_mismatch_metadata.proftext b/llvm/test/Transforms/PGOProfile/Inputs/hash_mismatch_metadata.proftext new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/PGOProfile/Inputs/hash_mismatch_metadata.proftext @@ -0,0 +1,17 @@ +:ir +:entry_first +foo +# Func Hash: +11111 +# Num Counters: +1 +# Counter Values: +100 + +bar +# Func Hash: +11111 +# Num Counters: +1 +# Counter Values: +100 diff --git a/llvm/test/Transforms/PGOProfile/hash_mismatch_metadata.ll b/llvm/test/Transforms/PGOProfile/hash_mismatch_metadata.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/PGOProfile/hash_mismatch_metadata.ll @@ -0,0 +1,18 @@ +; RUN: llvm-profdata merge %S/Inputs/hash_mismatch_metadata.proftext -o %t.profdata +; RUN: opt < %s -mtriple=x86_64-linux-gnu -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s + +define void @foo() !annotation !1 { +entry: + ret void +} + +define void @bar() !annotation !2 { +entry: + ret void +} + +!1 = !{!"fake_metadata"} +!2 = !{!"instr_prof_hash_mismatch"} + +; CHECK-DAG: !{{[0-9]+}} = !{!"fake_metadata", !"instr_prof_hash_mismatch"} +; CHECK-DAG: !{{[0-9]+}} = !{!"instr_prof_hash_mismatch"}