MLIR 24.0.0git
LLVMRemarkImport.cpp
Go to the documentation of this file.
1//===- LLVMRemarkImport.cpp - Import LLVM remarks into MLIR ---------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10
11#include "mlir/IR/Diagnostics.h"
12#include "mlir/IR/MLIRContext.h"
13#include "mlir/IR/Operation.h"
14#include "mlir/IR/SymbolTable.h"
15
16#include "llvm/ADT/Twine.h"
17#include "llvm/IR/DiagnosticInfo.h"
18#include "llvm/IR/DiagnosticPrinter.h"
19#include "llvm/IR/Function.h"
20#include "llvm/IR/GlobalValue.h"
21#include "llvm/Remarks/Remark.h"
22#include "llvm/Remarks/RemarkParser.h"
23#include "llvm/Support/Error.h"
24#include "llvm/Support/raw_ostream.h"
25
26using namespace mlir;
27
28//===----------------------------------------------------------------------===//
29// Locations
30//===----------------------------------------------------------------------===//
31
32/// Returns the location of the symbol `functionName` inside `anchor`, or the
33/// location of `anchor` if there is no such symbol.
35 llvm::StringMap<Location> &cache,
36 StringRef functionName) {
37 if (functionName.empty() || !anchor->hasTrait<OpTrait::SymbolTable>())
38 return anchor->getLoc();
39 auto it = cache.find(functionName);
40 if (it != cache.end())
41 return it->second;
42 Location loc = anchor->getLoc();
43 if (Operation *symbol = SymbolTable::lookupSymbolIn(anchor, functionName))
44 loc = symbol->getLoc();
45 cache.try_emplace(functionName, loc);
46 return loc;
47}
48
50 llvm::StringMap<Location> &cache,
51 StringRef file, unsigned line, unsigned column,
52 StringRef functionName) {
53 if (!file.empty() && line != 0)
54 return FileLineColLoc::get(anchor->getContext(), file, line, column);
55 return getFunctionLocation(anchor, cache, functionName);
56}
57
58static Location
59resolveLocation(Operation *anchor, llvm::StringMap<Location> &cache,
60 const llvm::DiagnosticInfoWithLocationBase &diag) {
61 StringRef functionName = diag.getFunction().getName();
62 if (!diag.isLocationAvailable())
63 return resolveLocation(anchor, cache, "", 0, 0, functionName);
64 llvm::DiagnosticLocation loc = diag.getLocation();
65 return resolveLocation(anchor, cache, loc.getAbsolutePath(), loc.getLine(),
66 loc.getColumn(), functionName);
67}
68
69//===----------------------------------------------------------------------===//
70// Remark conversion
71//===----------------------------------------------------------------------===//
72
73namespace {
74/// The fields of an LLVM remark that are imported, shared by the live and the
75/// serialized paths.
76struct ImportedRemark {
77 remark::RemarkKind kind = remark::RemarkKind::RemarkUnknown;
78 StringRef passName;
79 StringRef remarkName;
80 StringRef functionName;
81 std::string message;
82 std::optional<uint64_t> hotness;
83 SmallVector<std::pair<StringRef, StringRef>> args;
84};
85} // namespace
86
87static remark::RemarkKind getRemarkKind(llvm::DiagnosticKind kind) {
88 switch (kind) {
89 case llvm::DK_OptimizationRemark:
90 case llvm::DK_MachineOptimizationRemark:
92 case llvm::DK_OptimizationRemarkMissed:
93 case llvm::DK_MachineOptimizationRemarkMissed:
95 case llvm::DK_OptimizationRemarkAnalysis:
96 case llvm::DK_OptimizationRemarkAnalysisFPCommute:
97 case llvm::DK_OptimizationRemarkAnalysisAliasing:
98 case llvm::DK_MachineOptimizationRemarkAnalysis:
100 case llvm::DK_OptimizationFailure:
102 default:
104 }
105}
106
107static remark::RemarkKind getRemarkKind(llvm::remarks::Type type) {
108 switch (type) {
109 case llvm::remarks::Type::Passed:
111 case llvm::remarks::Type::Missed:
113 case llvm::remarks::Type::Analysis:
114 case llvm::remarks::Type::AnalysisFPCommute:
115 case llvm::remarks::Type::AnalysisAliasing:
117 case llvm::remarks::Type::Failure:
119 case llvm::remarks::Type::Unknown:
121 }
122 llvm_unreachable("unknown remark type");
123}
124
125/// Returns the MLIR remark category of the LLVM pass `passName`.
126static std::string getCategory(StringRef passName) {
127 return (llvm::Twine(remark::llvmRemarkCategoryPrefix) + passName).str();
128}
129
130/// Renames the argument keys that the remark engine uses itself.
131static std::string getArgKey(StringRef key) {
132 if (key == "Remark" || key == "RemarkId" || key == "RelatedTo")
133 return ("LLVM" + key).str();
134 return key.str();
135}
136
138 Location loc, const ImportedRemark &imported) {
139 std::string category = getCategory(imported.passName);
140 remark::RemarkOpts opts = remark::RemarkOpts::name(imported.remarkName)
141 .category(category)
142 .function(imported.functionName);
144 switch (imported.kind) {
146 inFlight = engine.emitOptimizationRemark(loc, opts);
147 break;
149 inFlight = engine.emitOptimizationRemarkMiss(loc, opts);
150 break;
152 inFlight = engine.emitOptimizationRemarkFailure(loc, opts);
153 break;
155 inFlight = engine.emitOptimizationRemarkAnalysis(loc, opts);
156 break;
158 return;
159 }
160 if (!inFlight)
161 return;
162
163 inFlight << StringRef(imported.message);
164 for (const auto &[key, value] : imported.args) {
165 // Plain strings are already part of the message.
166 if (key == "String")
167 continue;
168 inFlight << remark::detail::Remark::Arg(getArgKey(key), value);
169 }
170 if (imported.hotness)
171 inFlight << remark::detail::Remark::Arg("Hotness", *imported.hotness);
172}
173
175 const llvm::DiagnosticInfoOptimizationBase &diag) {
176 ImportedRemark imported;
177 imported.kind =
178 getRemarkKind(static_cast<llvm::DiagnosticKind>(diag.getKind()));
179 imported.passName = diag.getPassName();
180 imported.remarkName = diag.getRemarkName();
181 imported.functionName =
182 llvm::GlobalValue::dropLLVMManglingEscape(diag.getFunction().getName());
183 imported.message = diag.getMsg();
184 imported.hotness = diag.getHotness();
185 for (const llvm::DiagnosticInfoOptimizationBase::Argument &arg :
186 diag.getArgs())
187 imported.args.emplace_back(arg.Key, arg.Val);
188 emitImportedRemark(engine, loc, imported);
189}
190
192 const llvm::remarks::Remark &remark) {
193 ImportedRemark imported;
194 imported.kind = getRemarkKind(remark.RemarkType);
195 imported.passName = remark.PassName;
196 imported.remarkName = remark.RemarkName;
197 imported.functionName = remark.FunctionName;
198 imported.message = remark.getArgsAsMsg();
199 imported.hotness = remark.Hotness;
200 for (const llvm::remarks::Argument &arg : remark.Args)
201 imported.args.emplace_back(arg.Key, arg.Val);
202 emitImportedRemark(engine, loc, imported);
203}
204
206 StringRef buffer,
207 llvm::remarks::Format format) {
209 anchor->getContext()->getRemarkEngine();
210 if (!engine)
211 return success();
212
214 llvm::remarks::createRemarkParser(format, buffer);
215 if (!parser) {
216 llvm::consumeError(parser.takeError());
217 return failure();
218 }
219
220 llvm::StringMap<Location> functionLocations;
221 while (true) {
223 (*parser)->next();
224 if (!next) {
225 llvm::Error error = next.takeError();
226 bool endOfFile = error.isA<llvm::remarks::EndOfFileError>();
227 llvm::consumeError(std::move(error));
228 return success(endOfFile);
229 }
230 const llvm::remarks::Remark &remark = **next;
231 Location loc = remark.Loc ? resolveLocation(anchor, functionLocations,
232 remark.Loc->SourceFilePath,
233 remark.Loc->SourceLine,
234 remark.Loc->SourceColumn,
235 remark.FunctionName)
236 : resolveLocation(anchor, functionLocations, "",
237 0, 0, remark.FunctionName);
238 importLLVMRemark(*engine, loc, remark);
239 }
240}
241
242//===----------------------------------------------------------------------===//
243// LLVMToMLIRDiagnosticHandler
244//===----------------------------------------------------------------------===//
245
247 Operation *anchor)
248 : anchor(anchor), engine(anchor->getContext()->getRemarkEngine()) {}
249
251 StringRef passName) const {
252 return (engine &&
253 engine->isAnalysisOptRemarkEnabled(getCategory(passName))) ||
254 DiagnosticHandler::isAnalysisRemarkEnabled(passName);
255}
256
258 StringRef passName) const {
259 return (engine && engine->isMissedOptRemarkEnabled(getCategory(passName))) ||
260 DiagnosticHandler::isMissedOptRemarkEnabled(passName);
261}
262
264 StringRef passName) const {
265 return (engine && engine->isPassedOptRemarkEnabled(getCategory(passName))) ||
266 DiagnosticHandler::isPassedOptRemarkEnabled(passName);
267}
268
270 return (engine && engine->isAnyRemarkEnabled()) ||
271 DiagnosticHandler::isAnyRemarkEnabled();
272}
273
275 const llvm::DiagnosticInfo &diag) {
276 if (const auto *optRemark =
277 dyn_cast<llvm::DiagnosticInfoOptimizationBase>(&diag)) {
278 remark::RemarkKind kind =
279 getRemarkKind(static_cast<llvm::DiagnosticKind>(optRemark->getKind()));
280 if (!engine ||
281 !engine->isRemarkEnabled(kind, getCategory(optRemark->getPassName())))
282 return false;
283 importLLVMRemark(*engine,
284 resolveLocation(anchor, functionLocations, *optRemark),
285 *optRemark);
286 return true;
287 }
288
289 std::string message;
290 llvm::raw_string_ostream os(message);
291 llvm::DiagnosticPrinterRawOStream printer(os);
292 diag.print(printer);
293 StringRef text = StringRef(message).rtrim();
294
295 Location loc = anchor->getLoc();
296 if (const auto *withLoc = dyn_cast<llvm::DiagnosticInfoUnsupported>(&diag)) {
297 loc = resolveLocation(anchor, functionLocations, *withLoc);
298 // The location is carried by `loc` already.
299 text.consume_front(withLoc->getLocationStr() + ": ");
300 }
301
302 switch (diag.getSeverity()) {
303 case llvm::DS_Error:
304 emitError(loc) << text;
305 break;
306 case llvm::DS_Warning:
307 emitWarning(loc) << text;
308 break;
309 case llvm::DS_Remark:
310 case llvm::DS_Note:
311 emitRemark(loc) << text;
312 break;
313 }
314 return true;
315}
return success()
static void emitImportedRemark(remark::detail::RemarkEngine &engine, Location loc, const ImportedRemark &imported)
static void importLLVMRemark(remark::detail::RemarkEngine &engine, Location loc, const llvm::DiagnosticInfoOptimizationBase &diag)
static remark::RemarkKind getRemarkKind(llvm::DiagnosticKind kind)
static Location getFunctionLocation(Operation *anchor, llvm::StringMap< Location > &cache, StringRef functionName)
Returns the location of the symbol functionName inside anchor, or the location of anchor if there is ...
static std::string getArgKey(StringRef key)
Renames the argument keys that the remark engine uses itself.
static Location resolveLocation(Operation *anchor, llvm::StringMap< Location > &cache, StringRef file, unsigned line, unsigned column, StringRef functionName)
static std::string getCategory(StringRef passName)
Returns the MLIR remark category of the LLVM pass passName.
b getContext())
static std::string diag(const llvm::Value &value)
static FileLineColLoc get(StringAttr filename, unsigned line, unsigned column)
Definition Location.cpp:157
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition Location.h:76
remark::detail::RemarkEngine * getRemarkEngine()
Returns the remark engine for this context, or nullptr if none has been set.
A trait used to provide symbol table functionalities to a region operation.
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Definition Operation.h:801
Location getLoc()
The source location the operation was defined or derived from.
Definition Operation.h:240
MLIRContext * getContext()
Return the context this operation is associated with.
Definition Operation.h:233
static Operation * lookupSymbolIn(Operation *op, StringAttr symbol)
Returns the operation registered with the given symbol name with the regions of 'symbolTableOp'.
bool isMissedOptRemarkEnabled(StringRef passName) const override
bool isAnalysisRemarkEnabled(StringRef passName) const override
bool handleDiagnostics(const llvm::DiagnosticInfo &diag) override
bool isPassedOptRemarkEnabled(StringRef passName) const override
A wrapper for linking remarks by query - searches the engine's registry at stream time and links to a...
Definition Remarks.h:402
InFlightRemark emitOptimizationRemarkFailure(Location loc, RemarkOpts opts)
Report a failed optimization remark, this will create an InFlightRemark that can be used to build the...
Definition Remarks.cpp:237
InFlightRemark emitOptimizationRemark(Location loc, RemarkOpts opts)
Report a successful remark, this will create an InFlightRemark that can be used to build the remark u...
Definition Remarks.cpp:225
InFlightRemark emitOptimizationRemarkMiss(Location loc, RemarkOpts opts)
Report a missed optimization remark that can be used to build the remark using the << operator.
Definition Remarks.cpp:231
InFlightRemark emitOptimizationRemarkAnalysis(Location loc, RemarkOpts opts)
Report an analysis remark, this will create an InFlightRemark that can be used to build the remark us...
Definition Remarks.cpp:243
constexpr llvm::StringLiteral llvmRemarkCategoryPrefix
Prefix of the category of remarks imported from LLVM.
LogicalResult importLLVMRemarks(Operation *anchor, StringRef buffer, llvm::remarks::Format format)
Parses buffer, a serialized LLVM remark file, and reports its remarks into the remark engine of the c...
RemarkKind
Categories describe the outcome of an transformation, not the mechanics of emitting/serializing remar...
Definition Remarks.h:70
@ RemarkPassed
An optimization was applied.
Definition Remarks.h:74
@ RemarkAnalysis
Informational context (e.g., analysis numbers) without a pass/fail outcome.
Definition Remarks.h:85
@ RemarkMissed
A profitable optimization opportunity was found but not applied.
Definition Remarks.h:77
@ RemarkFailure
The compiler attempted the optimization but failed (e.g., legality checks, or better opportunites).
Definition Remarks.h:81
Include the generated interface declarations.
InFlightDiagnostic emitWarning(Location loc)
Utility method to emit a warning message using this location.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
InFlightDiagnostic emitRemark(Location loc)
Utility method to emit a remark message using this location.
Options to create a Remark.
Definition Remarks.h:95
RemarkOpts function(StringRef v) const
Return a copy with the function name set.
Definition Remarks.h:124
RemarkOpts category(StringRef v) const
Return a copy with the category set.
Definition Remarks.h:112
static RemarkOpts name(StringRef n)
Definition Remarks.h:105