llvm.org GIT mirror llvm / f524386
[OptDiag] Updating Remarks in SampleProfile Updating remark API to newer OptimizationDiagnosticInfo API. This allows remarks to show up in diagnostic yaml file, and enables use of opt-viewer tool. Hotness information for remarks (L505 and L751) do not display hotness information, most likely due to profile information not being propagated yet. Unsure if this is the desired outcome. Patch by Tarun Rajendran. Differential Revision: https://reviews.llvm.org/D36127 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@310763 91177308-0d34-0410-b5e6-96231b3b80d8 Eli Friedman 2 years ago
7 changed file(s) with 103 addition(s) and 39 deletion(s). Raw diff Collapse all Expand all
424424 Argument(StringRef Key, unsigned N);
425425 Argument(StringRef Key, uint64_t N);
426426 Argument(StringRef Key, bool B) : Key(Key), Val(B ? "true" : "false") {}
427 Argument(StringRef Key, DebugLoc dl);
427428 };
428429
429430 /// \p PassName is the name of the pass emitting this diagnostic. \p
110110 Instruction *promoteIndirectCall(Instruction *Inst, Function *F, uint64_t Count,
111111 uint64_t TotalCount,
112112 bool AttachProfToDirectCall,
113 OptimizationRemarkEmitter *ORE = nullptr);
113 OptimizationRemarkEmitter *ORE);
114114
115115 /// Options for the frontend instrumentation based profiling pass.
116116 struct InstrProfOptions {
232232 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, uint64_t N)
233233 : Key(Key), Val(utostr(N)) {}
234234
235 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, DebugLoc Loc)
236 : Key(Key), Loc(Loc) {
237 if (Loc) {
238 Val = (Loc->getFilename() + ":" + Twine(Loc.getLine()) + ":" +
239 Twine(Loc.getCol())).str();
240 } else {
241 Val = "";
242 }
243 }
244
235245 void DiagnosticInfoOptimizationBase::print(DiagnosticPrinter &DP) const {
236246 DP << getLocationStr() << ": " << getMsg();
237247 if (Hotness)
2828 #include "llvm/ADT/StringRef.h"
2929 #include "llvm/Analysis/AssumptionCache.h"
3030 #include "llvm/Analysis/LoopInfo.h"
31 #include "llvm/Analysis/OptimizationDiagnosticInfo.h"
3132 #include "llvm/Analysis/PostDominators.h"
3233 #include "llvm/IR/Constants.h"
3334 #include "llvm/IR/DebugInfo.h"
147148 SampleProfileLoader(StringRef Name = SampleProfileFile)
148149 : DT(nullptr), PDT(nullptr), LI(nullptr), ACT(nullptr), Reader(),
149150 Samples(nullptr), Filename(Name), ProfileIsValid(false),
150 TotalCollectedSamples(0) {}
151 TotalCollectedSamples(0), ORE(nullptr) {}
151152
152153 bool doInitialization(Module &M);
153 bool runOnModule(Module &M);
154 bool runOnModule(Module &M, ModuleAnalysisManager *AM);
154155 void setACT(AssumptionCacheTracker *A) { ACT = A; }
155156
156157 void dump() { Reader->dump(); }
157158
158159 protected:
159 bool runOnFunction(Function &F);
160 bool runOnFunction(Function &F, ModuleAnalysisManager *AM);
160161 unsigned getFunctionLoc(Function &F);
161162 bool emitAnnotations(Function &F);
162163 ErrorOr getInstWeight(const Instruction &I);
248249 /// This is the sum of all the samples collected in all the functions executed
249250 /// at runtime.
250251 uint64_t TotalCollectedSamples;
252
253 /// \brief Optimization Remark Emitter used to emit diagnostic remarks.
254 OptimizationRemarkEmitter *ORE;
251255 };
252256
253257 class SampleProfileLoaderLegacyPass : public ModulePass {
496500 bool FirstMark =
497501 CoverageTracker.markSamplesUsed(FS, LineOffset, Discriminator, R.get());
498502 if (FirstMark) {
499 const Function *F = Inst.getParent()->getParent();
500 LLVMContext &Ctx = F->getContext();
501 emitOptimizationRemark(
502 Ctx, DEBUG_TYPE, *F, DLoc,
503 Twine("Applied ") + Twine(*R) +
504 " samples from profile (offset: " + Twine(LineOffset) +
505 ((Discriminator) ? Twine(".") + Twine(Discriminator) : "") + ")");
503 if (Discriminator)
504 ORE->emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "AppliedSamples", &Inst)
505 << "Applied " << ore::NV("NumSamples", *R)
506 << " samples from profile (offset: "
507 << ore::NV("LineOffset", LineOffset) << "."
508 << ore::NV("Discriminator", Discriminator) << ")");
509 else
510 ORE->emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "AppliedSamples", &Inst)
511 << "Applied " << ore::NV("NumSamples", *R)
512 << " samples from profile (offset: "
513 << ore::NV("LineOffset", LineOffset) << ")");
506514 }
507515 DEBUG(dbgs() << " " << DLoc.getLine() << "."
508516 << DIL->getBaseDiscriminator() << ":" << Inst
668676 Function &F, DenseSet &ImportGUIDs) {
669677 DenseSet PromotedInsns;
670678 bool Changed = false;
671 LLVMContext &Ctx = F.getContext();
672679 std::function GetAssumptionCache = [&](
673680 Function &F) -> AssumptionCache & { return ACT->getAssumptionCache(F); };
674681 while (true) {
719726 // We set the probability to 80% taken to indicate that the static
720727 // call is likely taken.
721728 DI = dyn_cast(
722 promoteIndirectCall(I, CalledFunction, 80, 100, false)
729 promoteIndirectCall(I, CalledFunction, 80, 100, false, ORE)
723730 ->stripPointerCasts());
724731 PromotedInsns.insert(I);
725732 } else {
736743 continue;
737744 }
738745 DebugLoc DLoc = I->getDebugLoc();
746 BasicBlock *BB = I->getParent();
739747 if (InlineFunction(CallSite(DI), IFI)) {
740748 LocalChanged = true;
741 emitOptimizationRemark(Ctx, DEBUG_TYPE, F, DLoc,
742 Twine("inlined hot callee '") +
743 CalledFunction->getName() + "' into '" +
744 F.getName() + "'");
749 // The call to InlineFunction erases DI, so we can't pass it here.
750 ORE->emit(OptimizationRemark(DEBUG_TYPE, "HotInline", DLoc, BB)
751 << "inlined hot callee '"
752 << ore::NV("Callee", CalledFunction) << "' into '"
753 << ore::NV("Caller", &F) << "'");
745754 }
746755 }
747756 if (LocalChanged) {
12121221 << ".\n");
12131222 SmallVector Weights;
12141223 uint32_t MaxWeight = 0;
1215 DebugLoc MaxDestLoc;
1224 Instruction *MaxDestInst;
12161225 for (unsigned I = 0; I < TI->getNumSuccessors(); ++I) {
12171226 BasicBlock *Succ = TI->getSuccessor(I);
12181227 Edge E = std::make_pair(BB, Succ);
12311240 if (Weight != 0) {
12321241 if (Weight > MaxWeight) {
12331242 MaxWeight = Weight;
1234 MaxDestLoc = Succ->getFirstNonPHIOrDbgOrLifetime()->getDebugLoc();
1243 MaxDestInst = Succ->getFirstNonPHIOrDbgOrLifetime();
12351244 }
12361245 }
12371246 }
12461255 DEBUG(dbgs() << "SUCCESS. Found non-zero weights.\n");
12471256 TI->setMetadata(llvm::LLVMContext::MD_prof,
12481257 MDB.createBranchWeights(Weights));
1249 emitOptimizationRemark(
1250 Ctx, DEBUG_TYPE, F, MaxDestLoc,
1251 Twine("most popular destination for conditional branches at ") +
1252 ((BranchLoc) ? Twine(BranchLoc->getFilename() + ":" +
1253 Twine(BranchLoc.getLine()) + ":" +
1254 Twine(BranchLoc.getCol()))
1255 : Twine("")));
1258 ORE->emit(OptimizationRemark(DEBUG_TYPE, "PopularDest", MaxDestInst)
1259 << "most popular destination for conditional branches at "
1260 << ore::NV("CondBranchesLoc", BranchLoc));
12561261 } else {
12571262 DEBUG(dbgs() << "SKIPPED. All branch weights are zero.\n");
12581263 }
14321437 return new SampleProfileLoaderLegacyPass(Name);
14331438 }
14341439
1435 bool SampleProfileLoader::runOnModule(Module &M) {
1440 bool SampleProfileLoader::runOnModule(Module &M, ModuleAnalysisManager *AM) {
14361441 if (!ProfileIsValid)
14371442 return false;
14381443
14641469 for (auto &F : M)
14651470 if (!F.isDeclaration()) {
14661471 clearFunctionData();
1467 retval |= runOnFunction(F);
1472 retval |= runOnFunction(F, AM);
14681473 }
14691474 if (M.getProfileSummary() == nullptr)
14701475 M.setProfileSummary(Reader->getSummary().getMD(M.getContext()));
14741479 bool SampleProfileLoaderLegacyPass::runOnModule(Module &M) {
14751480 // FIXME: pass in AssumptionCache correctly for the new pass manager.
14761481 SampleLoader.setACT(&getAnalysis());
1477 return SampleLoader.runOnModule(M);
1478 }
1479
1480 bool SampleProfileLoader::runOnFunction(Function &F) {
1482 return SampleLoader.runOnModule(M, nullptr);
1483 }
1484
1485 bool SampleProfileLoader::runOnFunction(Function &F, ModuleAnalysisManager *AM) {
14811486 F.setEntryCount(0);
1487 std::unique_ptr OwnedORE;
1488 if (AM) {
1489 auto &FAM =
1490 AM->getResult(*F.getParent())
1491 .getManager();
1492 ORE = &FAM.getResult(F);
1493 } else {
1494 OwnedORE = make_unique(&F);
1495 ORE = OwnedORE.get();
1496 }
14821497 Samples = Reader->getSamplesFor(F);
14831498 if (Samples && !Samples->empty())
14841499 return emitAnnotations(F);
14931508
14941509 SampleLoader.doInitialization(M);
14951510
1496 if (!SampleLoader.runOnModule(M))
1511 if (!SampleLoader.runOnModule(M, &AM))
14971512 return PreservedAnalyses::all();
14981513
14991514 return PreservedAnalyses::none();
None ; RUN: opt < %s -instcombine -sample-profile -sample-profile-file=%S/Inputs/cov-zero-samples.prof -sample-profile-check-record-coverage=100 -pass-remarks=sample-profile -o /dev/null 2>&1 | FileCheck %s
1 ; RUN: opt < %s -passes="function(instcombine),sample-profile" -sample-profile-file=%S/Inputs/cov-zero-samples.prof -sample-profile-check-record-coverage=100 -pass-remarks=sample-profile -o /dev/null 2>&1 | FileCheck %s
0 ; RUN: opt < %s -instcombine -sample-profile -sample-profile-file=%S/Inputs/cov-zero-samples.prof -sample-profile-check-record-coverage=100 -pass-remarks=sample-profile -pass-remarks-analysis=sample-profile -o /dev/null 2>&1 | FileCheck %s
1 ; RUN: opt < %s -passes="function(instcombine),sample-profile" -sample-profile-file=%S/Inputs/cov-zero-samples.prof -sample-profile-check-record-coverage=100 -pass-remarks=sample-profile -pass-remarks-analysis=sample-profile -o /dev/null 2>&1 | FileCheck %s
22 ;
33 ; CHECK: remark: cov-zero-samples.cc:9:29: Applied 404065 samples from profile (offset: 2.1)
44 ; CHECK: remark: cov-zero-samples.cc:10:9: Applied 443089 samples from profile (offset: 3)
None ; RUN: opt < %s -instcombine -sample-profile -sample-profile-file=%S/Inputs/inline-coverage.prof -sample-profile-check-record-coverage=100 -sample-profile-check-sample-coverage=110 -pass-remarks=sample-profile -o /dev/null 2>&1 | FileCheck %s
1 ; RUN: opt < %s -passes="function(instcombine),sample-profile" -sample-profile-file=%S/Inputs/inline-coverage.prof -sample-profile-check-record-coverage=100 -sample-profile-check-sample-coverage=110 -pass-remarks=sample-profile -o /dev/null 2>&1 | FileCheck %s
0 ; RUN: opt < %s -instcombine -sample-profile -sample-profile-file=%S/Inputs/inline-coverage.prof -sample-profile-check-record-coverage=100 -sample-profile-check-sample-coverage=110 -pass-remarks=sample-profile -pass-remarks-analysis=sample-profile -o /dev/null 2>&1 | FileCheck %s
1 ; RUN: opt < %s -passes="function(instcombine),sample-profile" -sample-profile-file=%S/Inputs/inline-coverage.prof -sample-profile-check-record-coverage=100 -sample-profile-check-sample-coverage=110 -pass-remarks=sample-profile -pass-remarks-analysis=sample-profile -o /dev/null 2>&1 | FileCheck %s
22 ;
33 ; Original code:
44 ;
None ; RUN: opt < %s -sample-profile -sample-profile-file=%S/Inputs/remarks.prof -S -pass-remarks=sample-profile 2>&1 | FileCheck %s
0 ; RUN: opt < %s -sample-profile -sample-profile-file=%S/Inputs/remarks.prof -S -pass-remarks=sample-profile -pass-remarks-output=%t.opt.yaml 2>&1 | FileCheck %s
11 ; RUN: opt < %s -passes=sample-profile -sample-profile-file=%S/Inputs/remarks.prof -S -pass-remarks=sample-profile 2>&1 | FileCheck %s
2 ;
2 ; RUN: FileCheck %s -check-prefix=YAML < %t.opt.yaml
33 ; Original test case.
44 ;
55 ; 1 #include
2525
2626 ; The predicate almost always chooses the 'else' branch.
2727 ; CHECK: remark: remarks.cc:9:15: most popular destination for conditional branches at remarks.cc:6:9
28
29 ; Checking to see if YAML file is generated and contains remarks
30 ;YAML: --- !Passed
31 ;YAML-NEXT: Pass: sample-profile
32 ;YAML-NEXT: Name: HotInline
33 ;YAML-NEXT: DebugLoc: { File: remarks.cc, Line: 13, Column: 21 }
34 ;YAML-NEXT: Function: main
35 ;YAML-NEXT: Args:
36 ;YAML-NEXT: - String: 'inlined hot callee '''
37 ;YAML-NEXT: - Callee: _Z3foov
38 ;YAML-NEXT: DebugLoc: { File: remarks.cc, Line: 3, Column: 0 }
39 ;YAML-NEXT: - String: ''' into '''
40 ;YAML-NEXT: - Caller: main
41 ;YAML-NEXT: DebugLoc: { File: remarks.cc, Line: 13, Column: 0 }
42 ;YAML-NEXT: - String: ''''
43 ;YAML-NEXT: ...
44 ;YAML: --- !Analysis
45 ;YAML-NEXT: Pass: sample-profile
46 ;YAML-NEXT: Name: AppliedSamples
47 ;YAML-NEXT: DebugLoc: { File: remarks.cc, Line: 5, Column: 8 }
48 ;YAML-NEXT: Function: main
49 ;YAML-NEXT: Args:
50 ;YAML-NEXT: - String: 'Applied '
51 ;YAML-NEXT: - NumSamples: '18305'
52 ;YAML-NEXT: - String: ' samples from profile (offset: '
53 ;YAML-NEXT: - LineOffset: '2'
54 ;YAML-NEXT: - String: ')'
55 ;YAML-NEXT: ...
56 ;YAML: --- !Passed
57 ;YAML-NEXT: Pass: sample-profile
58 ;YAML-NEXT: Name: PopularDest
59 ;YAML-NEXT: DebugLoc: { File: remarks.cc, Line: 6, Column: 9 }
60 ;YAML-NEXT: Function: main
61 ;YAML-NEXT: Args:
62 ;YAML-NEXT: - String: 'most popular destination for conditional branches at '
63 ;YAML-NEXT: - CondBranchesLoc: 'remarks.cc:5:3'
64 ;YAML-NEXT: DebugLoc: { File: remarks.cc, Line: 5, Column: 3 }
65 ;YAML-NEXT: ...
2866
2967 ; Function Attrs: nounwind uwtable
3068 define i64 @_Z3foov() #0 !dbg !4 {