[profcheck] Add indirect call metadata
This commit is contained in:
parent
2c11a83691
commit
0a12548b08
@ -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))
|
||||
|
5
llvm/test/Transforms/JumpTableToSwitch/lit.local.cfg
Normal file
5
llvm/test/Transforms/JumpTableToSwitch/lit.local.cfg
Normal file
@ -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"))
|
34
llvm/test/Transforms/PGOProfile/profcheck-indirect-calls.ll
Normal file
34
llvm/test/Transforms/PGOProfile/profcheck-indirect-calls.ll
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user