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