xref: /llvm-project/llvm/lib/IR/LLVMRemarkStreamer.cpp (revision f686e4bbc20a837ff5230656431aec1abbd5f872)
17531a503SFrancis Visoiu Mistrih //===- llvm/IR/LLVMRemarkStreamer.cpp - Remark Streamer -*- C++ ---------*-===//
27531a503SFrancis Visoiu Mistrih //
37531a503SFrancis Visoiu Mistrih // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47531a503SFrancis Visoiu Mistrih // See https://llvm.org/LICENSE.txt for license information.
57531a503SFrancis Visoiu Mistrih // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67531a503SFrancis Visoiu Mistrih //
77531a503SFrancis Visoiu Mistrih //===----------------------------------------------------------------------===//
87531a503SFrancis Visoiu Mistrih //
97531a503SFrancis Visoiu Mistrih // This file contains the implementation of the conversion between IR
107531a503SFrancis Visoiu Mistrih // Diagnostics and serializable remarks::Remark objects.
117531a503SFrancis Visoiu Mistrih //
127531a503SFrancis Visoiu Mistrih //===----------------------------------------------------------------------===//
137531a503SFrancis Visoiu Mistrih 
147531a503SFrancis Visoiu Mistrih #include "llvm/IR/LLVMRemarkStreamer.h"
157531a503SFrancis Visoiu Mistrih #include "llvm/IR/DiagnosticInfo.h"
167531a503SFrancis Visoiu Mistrih #include "llvm/IR/Function.h"
177531a503SFrancis Visoiu Mistrih #include "llvm/IR/GlobalValue.h"
18e188aae4Sserge-sans-paille #include "llvm/Remarks/RemarkStreamer.h"
19af450eabSReid Kleckner #include "llvm/Support/FileSystem.h"
20e188aae4Sserge-sans-paille #include "llvm/Support/ToolOutputFile.h"
21c589730aSKrzysztof Parzyszek #include <optional>
227531a503SFrancis Visoiu Mistrih 
237531a503SFrancis Visoiu Mistrih using namespace llvm;
247531a503SFrancis Visoiu Mistrih 
257531a503SFrancis Visoiu Mistrih /// DiagnosticKind -> remarks::Type
toRemarkType(enum DiagnosticKind Kind)267531a503SFrancis Visoiu Mistrih static remarks::Type toRemarkType(enum DiagnosticKind Kind) {
277531a503SFrancis Visoiu Mistrih   switch (Kind) {
287531a503SFrancis Visoiu Mistrih   default:
297531a503SFrancis Visoiu Mistrih     return remarks::Type::Unknown;
307531a503SFrancis Visoiu Mistrih   case DK_OptimizationRemark:
317531a503SFrancis Visoiu Mistrih   case DK_MachineOptimizationRemark:
327531a503SFrancis Visoiu Mistrih     return remarks::Type::Passed;
337531a503SFrancis Visoiu Mistrih   case DK_OptimizationRemarkMissed:
347531a503SFrancis Visoiu Mistrih   case DK_MachineOptimizationRemarkMissed:
357531a503SFrancis Visoiu Mistrih     return remarks::Type::Missed;
367531a503SFrancis Visoiu Mistrih   case DK_OptimizationRemarkAnalysis:
377531a503SFrancis Visoiu Mistrih   case DK_MachineOptimizationRemarkAnalysis:
387531a503SFrancis Visoiu Mistrih     return remarks::Type::Analysis;
397531a503SFrancis Visoiu Mistrih   case DK_OptimizationRemarkAnalysisFPCommute:
407531a503SFrancis Visoiu Mistrih     return remarks::Type::AnalysisFPCommute;
417531a503SFrancis Visoiu Mistrih   case DK_OptimizationRemarkAnalysisAliasing:
427531a503SFrancis Visoiu Mistrih     return remarks::Type::AnalysisAliasing;
437531a503SFrancis Visoiu Mistrih   case DK_OptimizationFailure:
447531a503SFrancis Visoiu Mistrih     return remarks::Type::Failure;
457531a503SFrancis Visoiu Mistrih   }
467531a503SFrancis Visoiu Mistrih }
477531a503SFrancis Visoiu Mistrih 
487531a503SFrancis Visoiu Mistrih /// DiagnosticLocation -> remarks::RemarkLocation.
49c589730aSKrzysztof Parzyszek static std::optional<remarks::RemarkLocation>
toRemarkLocation(const DiagnosticLocation & DL)507531a503SFrancis Visoiu Mistrih toRemarkLocation(const DiagnosticLocation &DL) {
517531a503SFrancis Visoiu Mistrih   if (!DL.isValid())
52e842c06cSKazu Hirata     return std::nullopt;
537531a503SFrancis Visoiu Mistrih   StringRef File = DL.getRelativePath();
547531a503SFrancis Visoiu Mistrih   unsigned Line = DL.getLine();
557531a503SFrancis Visoiu Mistrih   unsigned Col = DL.getColumn();
567531a503SFrancis Visoiu Mistrih   return remarks::RemarkLocation{File, Line, Col};
577531a503SFrancis Visoiu Mistrih }
587531a503SFrancis Visoiu Mistrih 
597531a503SFrancis Visoiu Mistrih /// LLVM Diagnostic -> Remark
607531a503SFrancis Visoiu Mistrih remarks::Remark
toRemark(const DiagnosticInfoOptimizationBase & Diag) const617531a503SFrancis Visoiu Mistrih LLVMRemarkStreamer::toRemark(const DiagnosticInfoOptimizationBase &Diag) const {
627531a503SFrancis Visoiu Mistrih   remarks::Remark R; // The result.
637531a503SFrancis Visoiu Mistrih   R.RemarkType = toRemarkType(static_cast<DiagnosticKind>(Diag.getKind()));
647531a503SFrancis Visoiu Mistrih   R.PassName = Diag.getPassName();
657531a503SFrancis Visoiu Mistrih   R.RemarkName = Diag.getRemarkName();
667531a503SFrancis Visoiu Mistrih   R.FunctionName =
677531a503SFrancis Visoiu Mistrih       GlobalValue::dropLLVMManglingEscape(Diag.getFunction().getName());
687531a503SFrancis Visoiu Mistrih   R.Loc = toRemarkLocation(Diag.getLocation());
697531a503SFrancis Visoiu Mistrih   R.Hotness = Diag.getHotness();
707531a503SFrancis Visoiu Mistrih 
717531a503SFrancis Visoiu Mistrih   for (const DiagnosticInfoOptimizationBase::Argument &Arg : Diag.getArgs()) {
727531a503SFrancis Visoiu Mistrih     R.Args.emplace_back();
737531a503SFrancis Visoiu Mistrih     R.Args.back().Key = Arg.Key;
747531a503SFrancis Visoiu Mistrih     R.Args.back().Val = Arg.Val;
757531a503SFrancis Visoiu Mistrih     R.Args.back().Loc = toRemarkLocation(Arg.Loc);
767531a503SFrancis Visoiu Mistrih   }
777531a503SFrancis Visoiu Mistrih 
787531a503SFrancis Visoiu Mistrih   return R;
797531a503SFrancis Visoiu Mistrih }
807531a503SFrancis Visoiu Mistrih 
emit(const DiagnosticInfoOptimizationBase & Diag)817531a503SFrancis Visoiu Mistrih void LLVMRemarkStreamer::emit(const DiagnosticInfoOptimizationBase &Diag) {
827531a503SFrancis Visoiu Mistrih   if (!RS.matchesFilter(Diag.getPassName()))
837531a503SFrancis Visoiu Mistrih       return;
847531a503SFrancis Visoiu Mistrih 
857531a503SFrancis Visoiu Mistrih   // First, convert the diagnostic to a remark.
867531a503SFrancis Visoiu Mistrih   remarks::Remark R = toRemark(Diag);
877531a503SFrancis Visoiu Mistrih   // Then, emit the remark through the serializer.
887531a503SFrancis Visoiu Mistrih   RS.getSerializer().emit(R);
897531a503SFrancis Visoiu Mistrih }
907531a503SFrancis Visoiu Mistrih 
917531a503SFrancis Visoiu Mistrih char LLVMRemarkSetupFileError::ID = 0;
927531a503SFrancis Visoiu Mistrih char LLVMRemarkSetupPatternError::ID = 0;
937531a503SFrancis Visoiu Mistrih char LLVMRemarkSetupFormatError::ID = 0;
947531a503SFrancis Visoiu Mistrih 
setupLLVMOptimizationRemarks(LLVMContext & Context,StringRef RemarksFilename,StringRef RemarksPasses,StringRef RemarksFormat,bool RemarksWithHotness,std::optional<uint64_t> RemarksHotnessThreshold)957531a503SFrancis Visoiu Mistrih Expected<std::unique_ptr<ToolOutputFile>> llvm::setupLLVMOptimizationRemarks(
967531a503SFrancis Visoiu Mistrih     LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses,
977531a503SFrancis Visoiu Mistrih     StringRef RemarksFormat, bool RemarksWithHotness,
987d43c3baSFangrui Song     std::optional<uint64_t> RemarksHotnessThreshold) {
99*f686e4bbSserge-sans-paille   if (RemarksWithHotness || RemarksHotnessThreshold.value_or(1))
1007531a503SFrancis Visoiu Mistrih       Context.setDiagnosticsHotnessRequested(true);
1017531a503SFrancis Visoiu Mistrih 
1027531a503SFrancis Visoiu Mistrih   Context.setDiagnosticsHotnessThreshold(RemarksHotnessThreshold);
1037531a503SFrancis Visoiu Mistrih 
1047531a503SFrancis Visoiu Mistrih   if (RemarksFilename.empty())
1057531a503SFrancis Visoiu Mistrih     return nullptr;
1067531a503SFrancis Visoiu Mistrih 
1077531a503SFrancis Visoiu Mistrih   Expected<remarks::Format> Format = remarks::parseFormat(RemarksFormat);
1087531a503SFrancis Visoiu Mistrih   if (Error E = Format.takeError())
1097531a503SFrancis Visoiu Mistrih     return make_error<LLVMRemarkSetupFormatError>(std::move(E));
1107531a503SFrancis Visoiu Mistrih 
1117531a503SFrancis Visoiu Mistrih   std::error_code EC;
11282b3e28eSAbhina Sreeskantharajan   auto Flags = *Format == remarks::Format::YAML ? sys::fs::OF_TextWithCRLF
1137531a503SFrancis Visoiu Mistrih                                                 : sys::fs::OF_None;
1147531a503SFrancis Visoiu Mistrih   auto RemarksFile =
1157531a503SFrancis Visoiu Mistrih       std::make_unique<ToolOutputFile>(RemarksFilename, EC, Flags);
1167531a503SFrancis Visoiu Mistrih   // We don't use llvm::FileError here because some diagnostics want the file
1177531a503SFrancis Visoiu Mistrih   // name separately.
1187531a503SFrancis Visoiu Mistrih   if (EC)
1197531a503SFrancis Visoiu Mistrih     return make_error<LLVMRemarkSetupFileError>(errorCodeToError(EC));
1207531a503SFrancis Visoiu Mistrih 
1217531a503SFrancis Visoiu Mistrih   Expected<std::unique_ptr<remarks::RemarkSerializer>> RemarkSerializer =
1227531a503SFrancis Visoiu Mistrih       remarks::createRemarkSerializer(
1237531a503SFrancis Visoiu Mistrih           *Format, remarks::SerializerMode::Separate, RemarksFile->os());
1247531a503SFrancis Visoiu Mistrih   if (Error E = RemarkSerializer.takeError())
1257531a503SFrancis Visoiu Mistrih     return make_error<LLVMRemarkSetupFormatError>(std::move(E));
1267531a503SFrancis Visoiu Mistrih 
1277531a503SFrancis Visoiu Mistrih   // Create the main remark streamer.
1287531a503SFrancis Visoiu Mistrih   Context.setMainRemarkStreamer(std::make_unique<remarks::RemarkStreamer>(
1297531a503SFrancis Visoiu Mistrih       std::move(*RemarkSerializer), RemarksFilename));
1307531a503SFrancis Visoiu Mistrih 
1317531a503SFrancis Visoiu Mistrih   // Create LLVM's optimization remarks streamer.
1327531a503SFrancis Visoiu Mistrih   Context.setLLVMRemarkStreamer(
1337531a503SFrancis Visoiu Mistrih       std::make_unique<LLVMRemarkStreamer>(*Context.getMainRemarkStreamer()));
1347531a503SFrancis Visoiu Mistrih 
1357531a503SFrancis Visoiu Mistrih   if (!RemarksPasses.empty())
1367531a503SFrancis Visoiu Mistrih     if (Error E = Context.getMainRemarkStreamer()->setFilter(RemarksPasses))
1377531a503SFrancis Visoiu Mistrih       return make_error<LLVMRemarkSetupPatternError>(std::move(E));
1387531a503SFrancis Visoiu Mistrih 
139c55cf4afSBill Wendling   return std::move(RemarksFile);
1407531a503SFrancis Visoiu Mistrih }
1417531a503SFrancis Visoiu Mistrih 
setupLLVMOptimizationRemarks(LLVMContext & Context,raw_ostream & OS,StringRef RemarksPasses,StringRef RemarksFormat,bool RemarksWithHotness,std::optional<uint64_t> RemarksHotnessThreshold)1423acda917SWei Wang Error llvm::setupLLVMOptimizationRemarks(
1433acda917SWei Wang     LLVMContext &Context, raw_ostream &OS, StringRef RemarksPasses,
1443acda917SWei Wang     StringRef RemarksFormat, bool RemarksWithHotness,
1457d43c3baSFangrui Song     std::optional<uint64_t> RemarksHotnessThreshold) {
146*f686e4bbSserge-sans-paille   if (RemarksWithHotness || RemarksHotnessThreshold.value_or(1))
1477531a503SFrancis Visoiu Mistrih     Context.setDiagnosticsHotnessRequested(true);
1487531a503SFrancis Visoiu Mistrih 
1497531a503SFrancis Visoiu Mistrih   Context.setDiagnosticsHotnessThreshold(RemarksHotnessThreshold);
1507531a503SFrancis Visoiu Mistrih 
1517531a503SFrancis Visoiu Mistrih   Expected<remarks::Format> Format = remarks::parseFormat(RemarksFormat);
1527531a503SFrancis Visoiu Mistrih   if (Error E = Format.takeError())
1537531a503SFrancis Visoiu Mistrih     return make_error<LLVMRemarkSetupFormatError>(std::move(E));
1547531a503SFrancis Visoiu Mistrih 
1557531a503SFrancis Visoiu Mistrih   Expected<std::unique_ptr<remarks::RemarkSerializer>> RemarkSerializer =
1567531a503SFrancis Visoiu Mistrih       remarks::createRemarkSerializer(*Format,
1577531a503SFrancis Visoiu Mistrih                                       remarks::SerializerMode::Separate, OS);
1587531a503SFrancis Visoiu Mistrih   if (Error E = RemarkSerializer.takeError())
1597531a503SFrancis Visoiu Mistrih     return make_error<LLVMRemarkSetupFormatError>(std::move(E));
1607531a503SFrancis Visoiu Mistrih 
1617531a503SFrancis Visoiu Mistrih   // Create the main remark streamer.
1627531a503SFrancis Visoiu Mistrih   Context.setMainRemarkStreamer(
1637531a503SFrancis Visoiu Mistrih       std::make_unique<remarks::RemarkStreamer>(std::move(*RemarkSerializer)));
1647531a503SFrancis Visoiu Mistrih 
1657531a503SFrancis Visoiu Mistrih   // Create LLVM's optimization remarks streamer.
1667531a503SFrancis Visoiu Mistrih   Context.setLLVMRemarkStreamer(
1677531a503SFrancis Visoiu Mistrih       std::make_unique<LLVMRemarkStreamer>(*Context.getMainRemarkStreamer()));
1687531a503SFrancis Visoiu Mistrih 
1697531a503SFrancis Visoiu Mistrih   if (!RemarksPasses.empty())
1707531a503SFrancis Visoiu Mistrih     if (Error E = Context.getMainRemarkStreamer()->setFilter(RemarksPasses))
1717531a503SFrancis Visoiu Mistrih       return make_error<LLVMRemarkSetupPatternError>(std::move(E));
1727531a503SFrancis Visoiu Mistrih 
1737531a503SFrancis Visoiu Mistrih   return Error::success();
1747531a503SFrancis Visoiu Mistrih }
175