xref: /freebsd-src/contrib/llvm-project/llvm/lib/Analysis/ReplayInlineAdvisor.cpp (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
1*e8d8bef9SDimitry Andric //===- ReplayInlineAdvisor.cpp - Replay InlineAdvisor ---------------------===//
2*e8d8bef9SDimitry Andric //
3*e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*e8d8bef9SDimitry Andric //
7*e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
8*e8d8bef9SDimitry Andric //
9*e8d8bef9SDimitry Andric // This file implements ReplayInlineAdvisor that replays inline decisions based
10*e8d8bef9SDimitry Andric // on previous inline remarks from optimization remark log. This is a best
11*e8d8bef9SDimitry Andric // effort approach useful for testing compiler/source changes while holding
12*e8d8bef9SDimitry Andric // inlining steady.
13*e8d8bef9SDimitry Andric //
14*e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
15*e8d8bef9SDimitry Andric 
16*e8d8bef9SDimitry Andric #include "llvm/Analysis/ReplayInlineAdvisor.h"
17*e8d8bef9SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
18*e8d8bef9SDimitry Andric #include "llvm/IR/Instructions.h"
19*e8d8bef9SDimitry Andric #include "llvm/Support/LineIterator.h"
20*e8d8bef9SDimitry Andric 
21*e8d8bef9SDimitry Andric using namespace llvm;
22*e8d8bef9SDimitry Andric 
23*e8d8bef9SDimitry Andric #define DEBUG_TYPE "inline-replay"
24*e8d8bef9SDimitry Andric 
25*e8d8bef9SDimitry Andric ReplayInlineAdvisor::ReplayInlineAdvisor(
26*e8d8bef9SDimitry Andric     Module &M, FunctionAnalysisManager &FAM, LLVMContext &Context,
27*e8d8bef9SDimitry Andric     std::unique_ptr<InlineAdvisor> OriginalAdvisor, StringRef RemarksFile,
28*e8d8bef9SDimitry Andric     bool EmitRemarks)
29*e8d8bef9SDimitry Andric     : InlineAdvisor(M, FAM), OriginalAdvisor(std::move(OriginalAdvisor)),
30*e8d8bef9SDimitry Andric       HasReplayRemarks(false), EmitRemarks(EmitRemarks) {
31*e8d8bef9SDimitry Andric   auto BufferOrErr = MemoryBuffer::getFileOrSTDIN(RemarksFile);
32*e8d8bef9SDimitry Andric   std::error_code EC = BufferOrErr.getError();
33*e8d8bef9SDimitry Andric   if (EC) {
34*e8d8bef9SDimitry Andric     Context.emitError("Could not open remarks file: " + EC.message());
35*e8d8bef9SDimitry Andric     return;
36*e8d8bef9SDimitry Andric   }
37*e8d8bef9SDimitry Andric 
38*e8d8bef9SDimitry Andric   // Example for inline remarks to parse:
39*e8d8bef9SDimitry Andric   //   main:3:1.1: _Z3subii inlined into main at callsite sum:1 @ main:3:1.1
40*e8d8bef9SDimitry Andric   // We use the callsite string after `at callsite` to replay inlining.
41*e8d8bef9SDimitry Andric   line_iterator LineIt(*BufferOrErr.get(), /*SkipBlanks=*/true);
42*e8d8bef9SDimitry Andric   for (; !LineIt.is_at_eof(); ++LineIt) {
43*e8d8bef9SDimitry Andric     StringRef Line = *LineIt;
44*e8d8bef9SDimitry Andric     auto Pair = Line.split(" at callsite ");
45*e8d8bef9SDimitry Andric 
46*e8d8bef9SDimitry Andric     auto Callee = Pair.first.split(" inlined into").first.rsplit(": ").second;
47*e8d8bef9SDimitry Andric 
48*e8d8bef9SDimitry Andric     auto CallSite = Pair.second.split(";").first;
49*e8d8bef9SDimitry Andric 
50*e8d8bef9SDimitry Andric     if (Callee.empty() || CallSite.empty())
51*e8d8bef9SDimitry Andric       continue;
52*e8d8bef9SDimitry Andric 
53*e8d8bef9SDimitry Andric     std::string Combined = (Callee + CallSite).str();
54*e8d8bef9SDimitry Andric     InlineSitesFromRemarks.insert(Combined);
55*e8d8bef9SDimitry Andric   }
56*e8d8bef9SDimitry Andric 
57*e8d8bef9SDimitry Andric   HasReplayRemarks = true;
58*e8d8bef9SDimitry Andric }
59*e8d8bef9SDimitry Andric 
60*e8d8bef9SDimitry Andric std::unique_ptr<InlineAdvice> ReplayInlineAdvisor::getAdviceImpl(CallBase &CB) {
61*e8d8bef9SDimitry Andric   assert(HasReplayRemarks);
62*e8d8bef9SDimitry Andric 
63*e8d8bef9SDimitry Andric   Function &Caller = *CB.getCaller();
64*e8d8bef9SDimitry Andric   auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(Caller);
65*e8d8bef9SDimitry Andric 
66*e8d8bef9SDimitry Andric   if (InlineSitesFromRemarks.empty())
67*e8d8bef9SDimitry Andric     return std::make_unique<DefaultInlineAdvice>(this, CB, None, ORE,
68*e8d8bef9SDimitry Andric                                                  EmitRemarks);
69*e8d8bef9SDimitry Andric 
70*e8d8bef9SDimitry Andric   std::string CallSiteLoc = getCallSiteLocation(CB.getDebugLoc());
71*e8d8bef9SDimitry Andric   StringRef Callee = CB.getCalledFunction()->getName();
72*e8d8bef9SDimitry Andric   std::string Combined = (Callee + CallSiteLoc).str();
73*e8d8bef9SDimitry Andric   auto Iter = InlineSitesFromRemarks.find(Combined);
74*e8d8bef9SDimitry Andric 
75*e8d8bef9SDimitry Andric   Optional<InlineCost> InlineRecommended = None;
76*e8d8bef9SDimitry Andric   if (Iter != InlineSitesFromRemarks.end()) {
77*e8d8bef9SDimitry Andric     InlineRecommended = llvm::InlineCost::getAlways("found in replay");
78*e8d8bef9SDimitry Andric   }
79*e8d8bef9SDimitry Andric 
80*e8d8bef9SDimitry Andric   return std::make_unique<DefaultInlineAdvice>(this, CB, InlineRecommended, ORE,
81*e8d8bef9SDimitry Andric                                                EmitRemarks);
82*e8d8bef9SDimitry Andric }
83