diff options
| author | Mircea Trofin <mtrofin@google.com> | 2025-08-20 18:29:05 -0700 |
|---|---|---|
| committer | Mircea Trofin <mtrofin@google.com> | 2025-08-20 21:25:50 -0700 |
| commit | 0a12548b08d6f89704f4e988f0b4364ccc076263 (patch) | |
| tree | b2066fe40eebb6acb0889d497ae5b43d2f0f2d51 | |
| parent | 2c11a83691b7089d7a79e9f122dc521e6ea7e51e (diff) | |
[profcheck] Add indirect call metadatausers/mtrofin/08-20-_profcheck_add_indirect_call_metadata
| -rw-r--r-- | llvm/lib/Transforms/Utils/ProfileVerify.cpp | 44 | ||||
| -rw-r--r-- | llvm/test/Transforms/JumpTableToSwitch/lit.local.cfg | 5 | ||||
| -rw-r--r-- | llvm/test/Transforms/PGOProfile/profcheck-indirect-calls.ll | 34 |
3 files changed, 72 insertions, 11 deletions
diff --git a/llvm/lib/Transforms/Utils/ProfileVerify.cpp b/llvm/lib/Transforms/Utils/ProfileVerify.cpp index 41647f7717a4..cf8d6c043e0c 100644 --- a/llvm/lib/Transforms/Utils/ProfileVerify.cpp +++ b/llvm/lib/Transforms/Utils/ProfileVerify.cpp @@ -17,6 +17,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" #include "llvm/IR/ProfDataUtils.h" +#include "llvm/ProfileData/InstrProf.h" #include "llvm/Support/BranchProbability.h" #include "llvm/Support/CommandLine.h" @@ -36,6 +37,10 @@ static cl::opt<uint32_t> SelectFalseWeight( "profcheck-default-select-false-weight", cl::init(3U), cl::desc("When annotating `select` instructions, this value will be used " "for the second ('false') case.")); +static cl::opt<bool> AnnotateIndirectCalls( + "profcheck-annotate-indirect-calls", cl::init(true), + cl::desc("Also inject (if missing) MD_prof for indirect calls")); + namespace { class ProfileInjector { Function &F; @@ -92,12 +97,24 @@ bool ProfileInjector::inject() { return false; bool Changed = false; for (auto &BB : F) { - if (AnnotateSelect) { - for (auto &I : BB) { - if (isa<SelectInst>(I) && !I.getMetadata(LLVMContext::MD_prof)) - setBranchWeights(I, {SelectTrueWeight, SelectFalseWeight}, - /*IsExpected=*/false); - } + for (auto &I : BB) { + // Annotate instructions that support MD_prof metadata, such as `select` + // and indirect calls - *if* they don't already have that metadata. + if (AnnotateSelect && isa<SelectInst>(I) && + !I.getMetadata(LLVMContext::MD_prof)) + setBranchWeights(I, {SelectTrueWeight, SelectFalseWeight}, + /*IsExpected=*/false); + if (AnnotateIndirectCalls) + if (auto *CB = dyn_cast<CallBase>(&I)) + if (CB->isIndirectCall() && !CB->getMetadata(LLVMContext::MD_prof)) + // add a valid-format but bogus indirect call profile. Neither the + // GUIDs nor the counts are meant to matter. + annotateValueSite(*F.getParent(), *CB, + {{/*.Value=*/2345, /*.Count=*/10}, + {/*.Value=*/5678, /*.Count=*/20}}, + /*Sum=*/30, + InstrProfValueKind::IPVK_IndirectCallTarget, + /*MaxMDCount=*/30); } auto *Term = getTerminatorBenefitingFromMDProf(BB); if (!Term || Term->getMetadata(LLVMContext::MD_prof)) @@ -162,11 +179,16 @@ PreservedAnalyses ProfileVerifierPass::run(Function &F, if (EntryCount->getCount() == 0) return PreservedAnalyses::all(); for (const auto &BB : F) { - if (AnnotateSelect) { - for (const auto &I : BB) - if (isa<SelectInst>(I) && !I.getMetadata(LLVMContext::MD_prof)) - F.getContext().emitError( - "Profile verification failed: select annotation missing"); + for (const auto &I : BB) { + if (AnnotateSelect && isa<SelectInst>(I) && + !I.getMetadata(LLVMContext::MD_prof)) + F.getContext().emitError( + "Profile verification failed: select annotation missing"); + if (AnnotateIndirectCalls) + if (const auto *CB = dyn_cast<CallBase>(&I)) + if (CB->isIndirectCall() && !I.getMetadata(LLVMContext::MD_prof)) + F.getContext().emitError("Profile verification failed: indirect " + "call annotation missing"); } if (const auto *Term = ProfileInjector::getTerminatorBenefitingFromMDProf(BB)) diff --git a/llvm/test/Transforms/JumpTableToSwitch/lit.local.cfg b/llvm/test/Transforms/JumpTableToSwitch/lit.local.cfg new file mode 100644 index 000000000000..de5b8ebb5d42 --- /dev/null +++ b/llvm/test/Transforms/JumpTableToSwitch/lit.local.cfg @@ -0,0 +1,5 @@ +if bool(config.enable_profcheck): + # disable indirect call annotations here. The targets for JumpTableToSwitch + # are specific, and the profile injector is (intentionally) naive in what + # VP metadata it inserts. + config.substitutions.append(("opt", "opt -profcheck-annotate-indirect-calls=0"))
\ No newline at end of file diff --git a/llvm/test/Transforms/PGOProfile/profcheck-indirect-calls.ll b/llvm/test/Transforms/PGOProfile/profcheck-indirect-calls.ll new file mode 100644 index 000000000000..027395eff751 --- /dev/null +++ b/llvm/test/Transforms/PGOProfile/profcheck-indirect-calls.ll @@ -0,0 +1,34 @@ +; Check insertion and verification of indirect calls +; RUN: split-file %s %t +; RUN: opt -passes=prof-inject %t/inject.ll -S -o - | FileCheck %t/inject.ll +; RUN: opt -passes=prof-verify %t/verify-ok.ll -S -o - | FileCheck %t/verify-ok.ll +; RUN: not opt -passes=prof-verify %t/verify-bad.ll -S -o - 2>&1 | FileCheck %t/verify-bad.ll + +;--- inject.ll +define void @foo(ptr %f) { + call void %f() + ret void +} + +; CHECK: call void %f(), !prof !1 +; CHECK: !0 = !{!"function_entry_count", i64 1000} +; CHECK: !1 = !{!"VP", i32 0, i64 30, i64 2345, i64 10, i64 5678, i64 20} + +;--- verify-ok.ll +define void @foo(ptr %f) !prof !0 { + call void %f(), !prof !1 + ret void +} +!0 = !{!"function_entry_count", i64 10} +!1 = !{!"VP", i32 0, i64 100, i64 123, i64 50, i64 456, i64 50} + +; CHECK: call void %f(), !prof !1 +; CHECK: !1 = !{!"VP", i32 0, i64 100, i64 123, i64 50, i64 456, i64 50} + +;--- verify-bad.ll +define void @foo(ptr %f) !prof !0 { + call void %f() + ret void +} +!0 = !{!"function_entry_count", i64 10} +; CHECK: Profile verification failed: indirect call annotation missing |
