MLIR 24.0.0git
Remarks.h
Go to the documentation of this file.
1//===- Remarks.h - MLIR Optimization Remark ----------------------*- C++-*-===//
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//
9// This file defines utilities for emitting optimization remarks.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef MLIR_IR_REMARKS_H
14#define MLIR_IR_REMARKS_H
15
16#include "llvm/ADT/DenseSet.h"
17#include "llvm/ADT/StringExtras.h"
18#include "llvm/IR/DiagnosticInfo.h"
19#include "llvm/Remarks/Remark.h"
20#include "llvm/Support/FormatVariadic.h"
21#include "llvm/Support/Regex.h"
22
23#include "mlir/IR/Diagnostics.h"
24#include "mlir/IR/MLIRContext.h"
25#include "mlir/IR/Value.h"
26
27#include <atomic>
28#include <mutex>
29#include <optional>
30
31namespace mlir::remark {
32
33//===----------------------------------------------------------------------===//
34// RemarkId - Unique identifier for linking related remarks
35//===----------------------------------------------------------------------===//
36
37/// A unique identifier for a remark, used to link related remarks together.
38/// An invalid/empty ID has value 0.
39class RemarkId {
40public:
41 RemarkId() : id(0) {}
42 explicit RemarkId(uint64_t id) : id(id) {}
43
44 /// Check if this is a valid (non-zero) ID.
45 explicit operator bool() const { return id != 0; }
46
47 /// Get the raw ID value.
48 uint64_t getValue() const { return id; }
49
50 bool operator==(const RemarkId &other) const { return id == other.id; }
51 bool operator!=(const RemarkId &other) const { return id != other.id; }
52
53 /// Print the ID.
54 void print(llvm::raw_ostream &os) const { os << "remark-" << id; }
55
56private:
57 uint64_t id;
58};
59
60inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, RemarkId id) {
61 id.print(os);
62 return os;
63}
64
65/// Define an the set of categories to accept. By default none are, the provided
66/// regex matches against the category names for each kind of remark.
68 std::optional<std::string> all, passed, missed, analysis, failed;
69};
70
71/// Categories describe the outcome of an transformation, not the mechanics of
72/// emitting/serializing remarks.
73enum class RemarkKind {
75
76 /// An optimization was applied.
78
79 /// A profitable optimization opportunity was found but not applied.
81
82 /// The compiler attempted the optimization but failed (e.g., legality
83 /// checks, or better opportunites).
85
86 /// Informational context (e.g., analysis numbers) without a pass/fail
87 /// outcome.
89};
90
91using namespace llvm;
92
93namespace detail {
94class InFlightRemark; // forward declaration
95} // namespace detail
96
97/// Options to create a Remark
98struct RemarkOpts {
99 StringRef remarkName; // Identifiable name
100 StringRef categoryName; // Category name (subject to regex filtering)
101 StringRef subCategoryName; // Subcategory name
102 StringRef functionName; // Function name if available
103
104 /// Link to a related remark by explicit ID.
106
107 // Construct RemarkOpts from a remark name.
108 static RemarkOpts name(StringRef n) {
109 RemarkOpts o;
110 o.remarkName = n;
111 return o;
112 }
113
114 /// Return a copy with the category set.
115 RemarkOpts category(StringRef v) const {
116 auto copy = *this;
117 copy.categoryName = v;
118 return copy;
119 }
120 /// Return a copy with the subcategory set.
121 RemarkOpts subCategory(StringRef v) const {
122 auto copy = *this;
123 copy.subCategoryName = v;
124 return copy;
125 }
126 /// Return a copy with the function name set.
127 RemarkOpts function(StringRef v) const {
128 auto copy = *this;
129 copy.functionName = v;
130 return copy;
131 }
132
133 /// Link this remark to a previously emitted remark by explicit ID.
135 auto copy = *this;
136 copy.relatedId = id;
137 return copy;
138 }
139
140 /// Link this remark to a related remark that is still in flight.
141 /// Extracts the ID from the InFlightRemark.
142 inline RemarkOpts relatedTo(const detail::InFlightRemark &r) const;
143};
144
145} // namespace mlir::remark
146
147namespace mlir::remark::detail {
148//===----------------------------------------------------------------------===//
149// Remark Base Class
150//===----------------------------------------------------------------------===//
151class Remark {
152
153public:
155 RemarkOpts opts)
157 categoryName(opts.categoryName.str()),
159 remarkName(opts.remarkName.str()) {
160 if (!categoryName.empty() && !subCategoryName.empty()) {
161 (llvm::Twine(categoryName) + ":" + subCategoryName)
162 .toVector(fullCategoryName);
163 }
164 // Explicit ID linking from opts.
165 if (opts.relatedId)
167 }
168
169 // Remark argument that is a key-value pair that can be printed as machine
170 // parsable args. For Attribute arguments, the original attribute is also
171 // stored to allow custom streamers to handle them specially.
172 struct Arg {
173 std::string key;
174 std::string val;
175 /// Optional attribute storage for Attribute-based args. Allows streamers
176 /// to access the original attribute for custom handling.
177 std::optional<Attribute> attr;
178 /// Generated RelatedTo argument, distinct from a user-supplied argument.
179 bool isLink = false;
180
181 Arg(llvm::StringRef m) : key("Remark"), val(m) {}
182 Arg(llvm::StringRef k, llvm::StringRef v) : key(k), val(v) {}
183 Arg(llvm::StringRef k, std::string v) : key(k), val(std::move(v)) {}
184 Arg(llvm::StringRef k, const char *v) : Arg(k, llvm::StringRef(v)) {}
185 Arg(llvm::StringRef k, Value v);
186 Arg(llvm::StringRef k, Type t);
187 Arg(llvm::StringRef k, Attribute a);
188 Arg(llvm::StringRef k, bool b) : key(k), val(b ? "true" : "false") {}
189
190 /// Check if this arg has an associated attribute.
191 bool hasAttribute() const { return attr.has_value(); }
192
193 /// Get the attribute if present.
194 Attribute getAttribute() const { return attr.value_or(Attribute()); }
195
196 // One constructor for all arithmetic types except bool.
197 template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T> &&
198 !std::is_same_v<T, bool>>>
199 Arg(llvm::StringRef k, T v) : key(k) {
200 if constexpr (std::is_floating_point_v<T>) {
201 llvm::raw_string_ostream os(val);
202 os << v;
203 } else if constexpr (std::is_signed_v<T>) {
204 val = llvm::itostr(static_cast<long long>(v));
205 } else {
206 val = llvm::utostr(static_cast<unsigned long long>(v));
207 }
208 }
209 };
210
211 void insert(llvm::StringRef s);
212 void insert(Arg a);
213
214 void print(llvm::raw_ostream &os, bool printLocation = false) const;
215
216 Location getLocation() const { return loc; }
217 /// Diagnostic -> Remark
218 llvm::remarks::Remark generateRemark() const;
219
220 StringRef getFunction() const {
221 if (!functionName.empty())
222 return functionName;
223 return "<unknown function>";
224 }
225
226 llvm::StringRef getCategoryName() const { return categoryName; }
227
228 llvm::StringRef getCombinedCategoryName() const {
229 if (categoryName.empty() && subCategoryName.empty())
230 return {};
231 if (subCategoryName.empty())
232 return categoryName;
233 if (categoryName.empty())
234 return subCategoryName;
235 return fullCategoryName;
236 }
237
238 StringRef getRemarkName() const {
239 if (remarkName.empty())
240 return "<unknown remark name>";
241 return remarkName;
242 }
243
244 std::string getMsg() const;
245
246 /// Return arguments, owned until mutation or destruction.
247 ArrayRef<Arg> getArgs() const { return args; }
248
249 llvm::remarks::Type getRemarkType() const;
250
251 //===--------------------------------------------------------------------===//
252 // Remark Linking Support
253 //===--------------------------------------------------------------------===//
254
255 /// Get this remark's unique ID (0 if not assigned).
256 RemarkId getId() const { return id; }
257
258 /// Set this remark's unique ID. Also adds it as an Arg for serialization.
259 void setId(RemarkId newId) {
260 id = newId;
261 if (id)
262 args.emplace_back("RemarkId", llvm::utostr(id.getValue()));
263 }
264
265 /// Get the list of related remark IDs.
267
268 /// Replace the list of related remark IDs.
270
271 /// Add a related ID and its generated argument.
272 void addRelatedRemark(RemarkId relatedId) {
273 if (!relatedId)
274 return;
275 relatedRemarks.push_back(relatedId);
276 Arg &arg =
277 args.emplace_back("RelatedTo", llvm::utostr(relatedId.getValue()));
278 arg.isLink = true;
279 }
280
281 /// Check if this remark has any related remarks.
282 bool hasRelatedRemarks() const { return !relatedRemarks.empty(); }
283
284 /// Get the remark kind.
286
287 StringRef getRemarkTypeString() const;
288
289protected:
290 /// Keeps the MLIR diagnostic kind, which is used to determine the
291 /// diagnostic kind in the LLVM remark streamer.
293 /// Name of the covering function like interface.
294 /// Stored as std::string to ensure the Remark owns its data.
295 std::string functionName;
296
298 /// Category name e.g., "Unroll" or "UnrollAndJam".
299 /// Stored as std::string to ensure the Remark owns its data.
300 std::string categoryName;
301
302 /// Sub category name e.g., "Loop Optimizer".
303 /// Stored as std::string to ensure the Remark owns its data.
304 std::string subCategoryName;
305
306 /// Combined name for category and sub-category
308
309 /// Remark identifier.
310 /// Stored as std::string to ensure the Remark owns its data.
311 std::string remarkName;
312
313 /// Args collected via the streaming interface.
315
316 /// Unique ID for this remark (assigned by RemarkEngine).
318
319 /// IDs of related remarks (e.g., parent analysis that enabled this opt).
321
322private:
323 /// Convert the MLIR diagnostic severity to LLVM diagnostic severity.
324 static llvm::DiagnosticSeverity
325 makeLLVMSeverity(DiagnosticSeverity severity) {
326 switch (severity) {
328 return llvm::DiagnosticSeverity::DS_Note;
330 return llvm::DiagnosticSeverity::DS_Warning;
332 return llvm::DiagnosticSeverity::DS_Error;
334 return llvm::DiagnosticSeverity::DS_Remark;
335 }
336 llvm_unreachable("Unknown diagnostic severity");
337 }
338 /// Convert the MLIR remark kind to LLVM diagnostic kind.
339 static llvm::DiagnosticKind makeLLVMKind(RemarkKind remarkKind) {
340 switch (remarkKind) {
342 return llvm::DiagnosticKind::DK_Generic;
344 return llvm::DiagnosticKind::DK_OptimizationRemark;
346 return llvm::DiagnosticKind::DK_OptimizationRemarkMissed;
348 return llvm::DiagnosticKind::DK_OptimizationFailure;
350 return llvm::DiagnosticKind::DK_OptimizationRemarkAnalysis;
351 }
352 llvm_unreachable("Unknown diagnostic kind");
353 }
354};
355
356inline Remark &operator<<(Remark &r, StringRef s) {
357 r.insert(s);
358 return r;
359}
360inline Remark &&operator<<(Remark &&r, StringRef s) {
361 r.insert(s);
362 return std::move(r);
363}
364inline Remark &operator<<(Remark &r, const Remark::Arg &kv) {
365 r.insert(kv);
366 return r;
367}
368
369//===----------------------------------------------------------------------===//
370// Shorthand aliases for different kinds of remarks.
371//===----------------------------------------------------------------------===//
372
373template <RemarkKind K, DiagnosticSeverity S>
374class OptRemarkBase final : public Remark {
375public:
377 : Remark(K, S, loc, opts) {}
378};
379
382
385
388
391
392class RemarkEngine;
393
394//===----------------------------------------------------------------------===//
395// InFlightRemark
396//===----------------------------------------------------------------------===//
397
398/// Lazy text building for zero cost string formatting.
400 llvm::StringRef key;
401 std::function<std::string()> thunk;
402};
403
404/// A wrapper for linking remarks by query - searches the engine's registry
405/// at stream time and links to all matching remarks.
406
407/// InFlightRemark is a RAII class that holds a reference to a Remark
408/// instance and allows to build the remark using the << operator. The remark
409/// is emitted when the InFlightRemark instance is destroyed, which happens
410/// when the scope ends or when the InFlightRemark instance is moved.
411/// Similar to InFlightDiagnostic, but for remarks.
413public:
414 explicit InFlightRemark(std::unique_ptr<Remark> diag)
415 : remark(std::move(diag)) {}
416
417 InFlightRemark(RemarkEngine &eng, std::unique_ptr<Remark> diag)
418 : owner(&eng), remark(std::move(diag)) {}
419
420 InFlightRemark() = default; // empty ctor
421
423 if (remark)
424 *remark << Remark::Arg(l.key, l.thunk());
425 return *this;
426 }
427
428 // Generic path, but *not* for Lazy
429 template <typename T, typename = std::enable_if_t<
430 !std::is_same_v<std::decay_t<T>, LazyTextBuild>>>
432 if (remark)
433 *remark << std::forward<T>(arg);
434 return *this;
435 }
436
437 explicit operator bool() const { return remark != nullptr; }
438
439 /// Get this remark's unique ID (for linking from other remarks).
440 RemarkId getId() const { return remark ? remark->getId() : RemarkId(); }
441
443
448
449private:
450 RemarkEngine *owner{nullptr};
451 std::unique_ptr<Remark> remark;
452};
453
454//===----------------------------------------------------------------------===//
455// Pluggable Remark Utilities
456//===----------------------------------------------------------------------===//
457
458/// Base class for MLIR remark streamers that is used to stream
459/// optimization remarks to the underlying remark streamer. The derived classes
460/// should implement the `streamOptimizationRemark` method to provide the
461/// actual streaming implementation.
463public:
464 virtual ~MLIRRemarkStreamerBase() = default;
465 /// Stream an optimization remark to the underlying remark streamer. It is
466 /// called by the RemarkEngine to stream the optimization remarks.
467 ///
468 /// It must be overridden by the derived classes to provide
469 /// the actual streaming implementation.
470 virtual void streamOptimizationRemark(const Remark &remark) = 0;
471
472 virtual void finalize() {} // optional
473};
474
475using ReportFn = llvm::unique_function<void(const Remark &)>;
476
477/// Base class for MLIR remark emitting policies that is used to emit
478/// optimization remarks to the underlying remark streamer. The derived classes
479/// should implement the `reportRemark` method to provide the actual emitting
480/// implementation.
482protected:
484
485public:
487 virtual ~RemarkEmittingPolicyBase() = default;
488
489 void initialize(ReportFn fn) { reportImpl = std::move(fn); }
490
491 virtual void reportRemark(const Remark &remark) = 0;
492 virtual void finalize() = 0;
493
494 /// Find previously reported remarks matching the given criteria.
495 /// Default returns empty -- only policies that store remarks (like
496 /// PolicyFinal) override this to enable query-based linking.
499 std::optional<RemarkKind> kind = std::nullopt) const {
500 return {};
501 }
502};
503
504//===----------------------------------------------------------------------===//
505// Remark Engine (MLIR Context will own this class)
506//===----------------------------------------------------------------------===//
507
509private:
510 /// Regex that filters missed optimization remarks: only matching one are
511 /// reported.
512 std::optional<llvm::Regex> missFilter;
513 /// The category for passed optimization remarks.
514 std::optional<llvm::Regex> passedFilter;
515 /// The category for analysis remarks.
516 std::optional<llvm::Regex> analysisFilter;
517 /// The category for failed optimization remarks.
518 std::optional<llvm::Regex> failedFilter;
519 /// The MLIR remark streamer that will be used to emit the remarks.
520 std::unique_ptr<MLIRRemarkStreamerBase> remarkStreamer;
521 /// The MLIR remark policy that will be used to emit the remarks.
522 std::unique_ptr<RemarkEmittingPolicyBase> remarkEmittingPolicy;
523 /// When is enabled, engine also prints remarks as mlir::emitRemarks.
524 bool printAsEmitRemarks = false;
525 /// Atomic counter for generating unique remark IDs.
526 std::atomic<uint64_t> nextRemarkId{1};
527
528 /// Emit a remark using the given maker function, which should return
529 /// a Remark instance. The remark will be emitted using the main
530 /// remark streamer.
531 template <typename RemarkT>
532 InFlightRemark makeRemark(Location loc, RemarkOpts opts);
533
534 template <typename RemarkT>
535 InFlightRemark emitIfEnabled(Location loc, RemarkOpts opts,
536 bool (RemarkEngine::*isEnabled)(StringRef)
537 const);
538 /// Report a remark.
539 void reportImpl(const Remark &remark);
540
541public:
542 /// Default constructor is deleted, use the other constructor.
543 RemarkEngine() = delete;
544
545 /// Constructs Remark engine with optional category names. If a category
546 /// name is not provided, it is not enabled. The category names are used to
547 /// filter the remarks that are emitted.
548 RemarkEngine(bool printAsEmitRemarks, const RemarkCategories &cats);
549
550 /// Destructor that will close the output file and reset the
551 /// main remark streamer.
553
554 /// Setup the remark engine with the given output path and format.
555 LogicalResult
556 initialize(std::unique_ptr<MLIRRemarkStreamerBase> streamer,
557 std::unique_ptr<RemarkEmittingPolicyBase> remarkEmittingPolicy,
558 std::string *errMsg);
559
560 /// Get the remark emitting policy.
562 return remarkEmittingPolicy.get();
563 }
564
565 /// Generate a unique ID for a new remark.
567 return RemarkId(nextRemarkId.fetch_add(1, std::memory_order_relaxed));
568 }
569
570 //===--------------------------------------------------------------------===//
571 // Remark Filtering - query which remarks are enabled
572 //===--------------------------------------------------------------------===//
573
574 /// Return true if missed optimization remarks are enabled for the given
575 /// category.
576 bool isMissedOptRemarkEnabled(StringRef categoryName) const;
577
578 /// Return true if passed optimization remarks are enabled for the given
579 /// category.
580 bool isPassedOptRemarkEnabled(StringRef categoryName) const;
581
582 /// Return true if analysis remarks are enabled for the given category.
583 bool isAnalysisOptRemarkEnabled(StringRef categoryName) const;
584
585 /// Return true if failed optimization remarks are enabled for the given
586 /// category.
587 bool isFailedOptRemarkEnabled(StringRef categoryName) const;
588
589 /// Return true if remarks of the given kind are enabled for the given
590 /// category. Always returns false for `RemarkKind::RemarkUnknown`.
591 bool isRemarkEnabled(RemarkKind kind, StringRef categoryName) const;
592
593 /// Return true if any kind of remark is enabled for the given category.
594 bool isAnyRemarkEnabled(StringRef categoryName) const {
595 return isMissedOptRemarkEnabled(categoryName) ||
596 isPassedOptRemarkEnabled(categoryName) ||
597 isFailedOptRemarkEnabled(categoryName) ||
598 isAnalysisOptRemarkEnabled(categoryName);
599 }
600
601 /// Return true if any kind of remark is enabled for any category, i.e. if at
602 /// least one category filter is active. This is a cheap check that external
603 /// remark producers can use before doing any work to build a remark.
604 bool isAnyRemarkEnabled() const {
605 return missFilter.has_value() || passedFilter.has_value() ||
606 analysisFilter.has_value() || failedFilter.has_value();
607 }
608
609 //===--------------------------------------------------------------------===//
610 // Remark Linking - query previously emitted remarks
611 //===--------------------------------------------------------------------===//
612
613 /// Find all remarks matching the given criteria. Delegates to the
614 /// emitting policy. Only works with policies that store remarks
615 /// (e.g. RemarkEmittingPolicyFinal); returns empty for PolicyAll.
618 std::optional<RemarkKind> kind = std::nullopt) const;
619
620 /// Report a remark.
621 void report(const Remark &&remark);
622
623 /// Report a successful remark, this will create an InFlightRemark
624 /// that can be used to build the remark using the << operator.
626
627 /// Report a missed optimization remark
628 /// that can be used to build the remark using the << operator.
630
631 /// Report a failed optimization remark, this will create an InFlightRemark
632 /// that can be used to build the remark using the << operator.
634
635 /// Report an analysis remark, this will create an InFlightRemark
636 /// that can be used to build the remark using the << operator.
638};
639
640template <typename Fn, typename... Args>
641inline InFlightRemark withEngine(Fn fn, Location loc, Args &&...args) {
642 MLIRContext *ctx = loc->getContext();
643
644 RemarkEngine *enginePtr = ctx->getRemarkEngine();
645
646 if (LLVM_UNLIKELY(enginePtr))
647 return (enginePtr->*fn)(loc, std::forward<Args>(args)...);
648
649 return {};
650}
651
652} // namespace mlir::remark::detail
653
654// Deferred definition: needs InFlightRemark to be complete.
659
660namespace mlir::remark {
661
662//===----------------------------------------------------------------------===//
663// Remark Emitting Policies
664//===----------------------------------------------------------------------===//
665
666/// Policy that emits all remarks.
668public:
670
671 void reportRemark(const detail::Remark &remark) override {
672 assert(reportImpl && "reportImpl is not set");
674 }
675 void finalize() override {}
676};
677
678/// Policy that emits only the last remark reported for each identity, see
679/// DenseMapInfo<Remark>. Remarks are stored until finalize().
681public:
683
684 void reportRemark(const detail::Remark &remark) override;
685
686 /// Emit each survivor once, grouping related remarks after their parents.
687 /// Visit roots with IDs in ID order, then ID-less roots in unspecified order.
688 /// Finally, start traversals from any unvisited remarks in ID order.
689 /// Links to IDs replaced in this batch are removed; IDs outside this batch
690 /// are preserved without validation. Call after reporting stops; callbacks
691 /// must not reenter the policy. A later call emits only new remarks.
692 void finalize() override;
693
694private:
695 std::mutex mutex;
696 llvm::DenseSet<detail::Remark> pendingRemarks;
697 /// IDs replaced in the current batch.
698 llvm::DenseSet<uint64_t> discardedIds;
699};
700
701/// Create a Reason with llvm::formatv formatting.
702template <class... Ts>
703inline detail::LazyTextBuild reason(const char *fmt, Ts &&...ts) {
704 return {"Reason", [=] { return llvm::formatv(fmt, ts...).str(); }};
705}
706
707/// Create a Suggestion with llvm::formatv formatting.
708template <class... Ts>
709inline detail::LazyTextBuild suggest(const char *fmt, Ts &&...ts) {
710 return {"Suggestion", [=] { return llvm::formatv(fmt, ts...).str(); }};
711}
712
713/// Create a Remark with llvm::formatv formatting.
714template <class... Ts>
715inline detail::LazyTextBuild add(const char *fmt, Ts &&...ts) {
716 return {"Remark", [=] { return llvm::formatv(fmt, ts...).str(); }};
717}
718
719template <class V>
720inline detail::LazyTextBuild metric(StringRef key, V &&v) {
721 using DV = std::decay_t<V>;
722 return {key, [key, vv = DV(std::forward<V>(v))]() mutable {
723 // Reuse Arg's formatting logic and return just the value string.
724 return detail::Remark::Arg(key, std::move(vv)).val;
725 }};
726}
727
728//===----------------------------------------------------------------------===//
729// Emitters
730//===----------------------------------------------------------------------===//
731
732/// Report an optimization remark that was passed.
734 return withEngine(&detail::RemarkEngine::emitOptimizationRemark, loc, opts);
735}
736
737/// Report an optimization remark that was missed.
740 opts);
741}
742
743/// Report an optimization remark that failed.
746 opts);
747}
748
749/// Report an optimization analysis remark.
752 opts);
753}
754
755//===----------------------------------------------------------------------===//
756// Setup
757//===----------------------------------------------------------------------===//
758
759/// Setup remarks for the context. This function will enable the remark engine
760/// and set the streamer to be used for optimization remarks. The remark
761/// categories are used to filter the remarks that will be emitted by the
762/// remark engine. If a category is not specified, it will not be emitted. If
763/// `printAsEmitRemarks` is true, the remarks will be printed as
764/// mlir::emitRemarks. 'streamer' must inherit from MLIRRemarkStreamerBase and
765/// will be used to stream the remarks.
767 MLIRContext &ctx,
768 std::unique_ptr<remark::detail::MLIRRemarkStreamerBase> streamer,
769 std::unique_ptr<remark::detail::RemarkEmittingPolicyBase>
770 remarkEmittingPolicy,
771 const remark::RemarkCategories &cats, bool printAsEmitRemarks = false);
772
773} // namespace mlir::remark
774
775/// Two remarks are the same for RemarkEmittingPolicyFinal when they have the
776/// same location, remark name, combined category name and kind.
777namespace llvm {
778template <>
779struct DenseMapInfo<mlir::remark::detail::Remark> {
780 static unsigned getHashValue(const mlir::remark::detail::Remark &remark) {
781 return llvm::hash_combine(
783 llvm::hash_value(remark.getRemarkName()),
784 llvm::hash_value(remark.getCombinedCategoryName()),
785 static_cast<unsigned>(remark.getRemarkKind()));
786 }
787
788 static bool isEqual(const mlir::remark::detail::Remark &lhs,
789 const mlir::remark::detail::Remark &rhs) {
790 return lhs.getLocation() == rhs.getLocation() &&
791 lhs.getRemarkName() == rhs.getRemarkName() &&
792 lhs.getCombinedCategoryName() == rhs.getCombinedCategoryName() &&
793 lhs.getRemarkKind() == rhs.getRemarkKind();
794 }
795};
796} // namespace llvm
797#endif // MLIR_IR_REMARKS_H
if(failed(verifyVectorMemoryOp(getOperation(), memrefType, getVectorType()))) return failure()
static void copy(Location loc, Value dst, Value src, Value size, OpBuilder &builder)
Copies the given number of bytes from src to dst pointers.
b
Return true if permutation is a valid permutation of the outer_dims_perm (case OuterOrInnerPerm::Oute...
#define add(a, b)
Attributes are known-constant values of operations.
Definition Attributes.h:25
MLIRContext * getContext() const
Return the context this attribute belongs to.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition Location.h:76
const void * getAsOpaquePointer() const
Methods for supporting PointerLikeTypeTraits.
Definition Location.h:105
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:71
remark::detail::RemarkEngine * getRemarkEngine()
Returns the remark engine for this context, or nullptr if none has been set.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
void reportRemark(const detail::Remark &remark) override
Definition Remarks.h:671
void finalize() override
Emit each survivor once, grouping related remarks after their parents.
Definition Remarks.cpp:408
void reportRemark(const detail::Remark &remark) override
Definition Remarks.cpp:396
A unique identifier for a remark, used to link related remarks together.
Definition Remarks.h:39
bool operator!=(const RemarkId &other) const
Definition Remarks.h:51
void print(llvm::raw_ostream &os) const
Print the ID.
Definition Remarks.h:54
bool operator==(const RemarkId &other) const
Definition Remarks.h:50
uint64_t getValue() const
Get the raw ID value.
Definition Remarks.h:48
RemarkId(uint64_t id)
Definition Remarks.h:42
A wrapper for linking remarks by query - searches the engine's registry at stream time and links to a...
Definition Remarks.h:412
InFlightRemark(RemarkEngine &eng, std::unique_ptr< Remark > diag)
Definition Remarks.h:417
InFlightRemark(std::unique_ptr< Remark > diag)
Definition Remarks.h:414
InFlightRemark(const InFlightRemark &)=delete
InFlightRemark & operator<<(const LazyTextBuild &l)
Definition Remarks.h:422
RemarkId getId() const
Get this remark's unique ID (for linking from other remarks).
Definition Remarks.h:440
InFlightRemark(InFlightRemark &&)=default
InFlightRemark & operator=(InFlightRemark &&)=default
InFlightRemark & operator<<(T &&arg)
Definition Remarks.h:431
InFlightRemark & operator=(const InFlightRemark &)=delete
Base class for MLIR remark streamers that is used to stream optimization remarks to the underlying re...
Definition Remarks.h:462
virtual void streamOptimizationRemark(const Remark &remark)=0
Stream an optimization remark to the underlying remark streamer.
OptRemarkBase(Location loc, RemarkOpts opts)
Definition Remarks.h:376
Base class for MLIR remark emitting policies that is used to emit optimization remarks to the underly...
Definition Remarks.h:481
virtual void reportRemark(const Remark &remark)=0
virtual SmallVector< RemarkId > findRemarks(const RemarkOpts &opts, std::optional< RemarkKind > kind=std::nullopt) const
Find previously reported remarks matching the given criteria.
Definition Remarks.h:498
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:253
bool isAnyRemarkEnabled(StringRef categoryName) const
Return true if any kind of remark is enabled for the given category.
Definition Remarks.h:594
bool isPassedOptRemarkEnabled(StringRef categoryName) const
Return true if passed optimization remarks are enabled for the given category.
Definition Remarks.cpp:212
bool isAnyRemarkEnabled() const
Return true if any kind of remark is enabled for any category, i.e.
Definition Remarks.h:604
void report(const Remark &&remark)
Report a remark.
Definition Remarks.cpp:280
bool isMissedOptRemarkEnabled(StringRef categoryName) const
Return true if missed optimization remarks are enabled for the given category.
Definition Remarks.cpp:208
RemarkId generateRemarkId()
Generate a unique ID for a new remark.
Definition Remarks.h:566
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:241
RemarkEmittingPolicyBase * getRemarkEmittingPolicy() const
Get the remark emitting policy.
Definition Remarks.h:561
SmallVector< RemarkId > findRemarks(const RemarkOpts &opts, std::optional< RemarkKind > kind=std::nullopt) const
Find all remarks matching the given criteria.
LogicalResult initialize(std::unique_ptr< MLIRRemarkStreamerBase > streamer, std::unique_ptr< RemarkEmittingPolicyBase > remarkEmittingPolicy, std::string *errMsg)
Setup the remark engine with the given output path and format.
Definition Remarks.cpp:293
RemarkEngine()=delete
Default constructor is deleted, use the other constructor.
bool isAnalysisOptRemarkEnabled(StringRef categoryName) const
Return true if analysis remarks are enabled for the given category.
Definition Remarks.cpp:216
bool isRemarkEnabled(RemarkKind kind, StringRef categoryName) const
Return true if remarks of the given kind are enabled for the given category.
Definition Remarks.cpp:224
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:247
~RemarkEngine()
Destructor that will close the output file and reset the main remark streamer.
Definition Remarks.cpp:285
bool isFailedOptRemarkEnabled(StringRef categoryName) const
Return true if failed optimization remarks are enabled for the given category.
Definition Remarks.cpp:220
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:259
void setRelatedRemarkIds(ArrayRef< RemarkId > ids)
Replace the list of related remark IDs.
Definition Remarks.cpp:47
RemarkId id
Unique ID for this remark (assigned by RemarkEngine).
Definition Remarks.h:317
std::string functionName
Name of the covering function like interface.
Definition Remarks.h:295
bool hasRelatedRemarks() const
Check if this remark has any related remarks.
Definition Remarks.h:282
void print(llvm::raw_ostream &os, bool printLocation=false) const
Print the remark to the given output stream.
Definition Remarks.cpp:89
void setId(RemarkId newId)
Set this remark's unique ID. Also adds it as an Arg for serialization.
Definition Remarks.h:259
RemarkId getId() const
Get this remark's unique ID (0 if not assigned).
Definition Remarks.h:256
ArrayRef< Arg > getArgs() const
Return arguments, owned until mutation or destruction.
Definition Remarks.h:247
SmallVector< Arg, 4 > args
Args collected via the streaming interface.
Definition Remarks.h:314
llvm::StringRef getCategoryName() const
Definition Remarks.h:226
StringRef getFunction() const
Definition Remarks.h:220
Remark(RemarkKind remarkKind, DiagnosticSeverity severity, Location loc, RemarkOpts opts)
Definition Remarks.h:154
llvm::remarks::Type getRemarkType() const
Definition Remarks.cpp:136
StringRef getRemarkTypeString() const
Definition Remarks.cpp:120
std::string remarkName
Remark identifier.
Definition Remarks.h:311
Location getLocation() const
Definition Remarks.h:216
std::string subCategoryName
Sub category name e.g., "Loop Optimizer".
Definition Remarks.h:304
RemarkKind getRemarkKind() const
Get the remark kind.
Definition Remarks.h:285
llvm::StringRef getCombinedCategoryName() const
Definition Remarks.h:228
void addRelatedRemark(RemarkId relatedId)
Add a related ID and its generated argument.
Definition Remarks.h:272
RemarkKind remarkKind
Keeps the MLIR diagnostic kind, which is used to determine the diagnostic kind in the LLVM remark str...
Definition Remarks.h:292
StringRef getRemarkName() const
Definition Remarks.h:238
SmallString< 64 > fullCategoryName
Combined name for category and sub-category.
Definition Remarks.h:307
SmallVector< RemarkId > relatedRemarks
IDs of related remarks (e.g., parent analysis that enabled this opt).
Definition Remarks.h:320
ArrayRef< RemarkId > getRelatedRemarkIds() const
Get the list of related remark IDs.
Definition Remarks.h:266
void insert(llvm::StringRef s)
Definition Remarks.cpp:44
llvm::remarks::Remark generateRemark() const
Diagnostic -> Remark.
Definition Remarks.cpp:152
std::string categoryName
Category name e.g., "Unroll" or "UnrollAndJam".
Definition Remarks.h:300
std::string getMsg() const
Definition Remarks.cpp:112
The OpAsmOpInterface, see OpAsmInterface.td for more details.
Definition CallGraph.h:229
AttrTypeReplacer.
OptRemarkBase< RemarkKind::RemarkMissed, DiagnosticSeverity::Remark > OptRemarkMissed
Definition Remarks.h:386
llvm::unique_function< void(const Remark &)> ReportFn
Definition Remarks.h:475
OptRemarkBase< RemarkKind::RemarkPassed, DiagnosticSeverity::Remark > OptRemarkPass
Definition Remarks.h:383
OptRemarkBase< RemarkKind::RemarkFailure, DiagnosticSeverity::Remark > OptRemarkFailure
Definition Remarks.h:389
OptRemarkBase< RemarkKind::RemarkAnalysis, DiagnosticSeverity::Remark > OptRemarkAnalysis
Definition Remarks.h:380
InFlightRemark withEngine(Fn fn, Location loc, Args &&...args)
Definition Remarks.h:641
Remark & operator<<(Remark &r, StringRef s)
Definition Remarks.h:356
detail::LazyTextBuild suggest(const char *fmt, Ts &&...ts)
Create a Suggestion with llvm::formatv formatting.
Definition Remarks.h:709
detail::InFlightRemark failed(Location loc, RemarkOpts opts)
Report an optimization remark that failed.
Definition Remarks.h:744
detail::InFlightRemark missed(Location loc, RemarkOpts opts)
Report an optimization remark that was missed.
Definition Remarks.h:738
detail::InFlightRemark analysis(Location loc, RemarkOpts opts)
Report an optimization analysis remark.
Definition Remarks.h:750
LogicalResult enableOptimizationRemarks(MLIRContext &ctx, std::unique_ptr< remark::detail::MLIRRemarkStreamerBase > streamer, std::unique_ptr< remark::detail::RemarkEmittingPolicyBase > remarkEmittingPolicy, const remark::RemarkCategories &cats, bool printAsEmitRemarks=false)
Setup remarks for the context.
detail::InFlightRemark passed(Location loc, RemarkOpts opts)
Report an optimization remark that was passed.
Definition Remarks.h:733
llvm::raw_ostream & operator<<(llvm::raw_ostream &os, RemarkId id)
Definition Remarks.h:60
detail::LazyTextBuild metric(StringRef key, V &&v)
Definition Remarks.h:720
detail::LazyTextBuild reason(const char *fmt, Ts &&...ts)
Create a Reason with llvm::formatv formatting.
Definition Remarks.h:703
RemarkKind
Categories describe the outcome of an transformation, not the mechanics of emitting/serializing remar...
Definition Remarks.h:73
@ RemarkPassed
An optimization was applied.
Definition Remarks.h:77
@ RemarkAnalysis
Informational context (e.g., analysis numbers) without a pass/fail outcome.
Definition Remarks.h:88
@ RemarkMissed
A profitable optimization opportunity was found but not applied.
Definition Remarks.h:80
@ RemarkFailure
The compiler attempted the optimization but failed (e.g., legality checks, or better opportunites).
Definition Remarks.h:84
Include the generated interface declarations.
DiagnosticSeverity
Defines the different supported severity of a diagnostic.
Definition Diagnostics.h:41
static bool isEqual(const mlir::remark::detail::Remark &lhs, const mlir::remark::detail::Remark &rhs)
Definition Remarks.h:788
static unsigned getHashValue(const mlir::remark::detail::Remark &remark)
Definition Remarks.h:780
Define an the set of categories to accept.
Definition Remarks.h:67
std::optional< std::string > missed
Definition Remarks.h:68
std::optional< std::string > all
Definition Remarks.h:68
std::optional< std::string > passed
Definition Remarks.h:68
std::optional< std::string > analysis
Definition Remarks.h:68
std::optional< std::string > failed
Definition Remarks.h:68
Options to create a Remark.
Definition Remarks.h:98
RemarkOpts function(StringRef v) const
Return a copy with the function name set.
Definition Remarks.h:127
StringRef subCategoryName
Definition Remarks.h:101
RemarkOpts subCategory(StringRef v) const
Return a copy with the subcategory set.
Definition Remarks.h:121
RemarkOpts relatedTo(RemarkId id) const
Link this remark to a previously emitted remark by explicit ID.
Definition Remarks.h:134
RemarkOpts category(StringRef v) const
Return a copy with the category set.
Definition Remarks.h:115
RemarkId relatedId
Link to a related remark by explicit ID.
Definition Remarks.h:105
static RemarkOpts name(StringRef n)
Definition Remarks.h:108
Lazy text building for zero cost string formatting.
Definition Remarks.h:399
std::function< std::string()> thunk
Definition Remarks.h:401
Arg(llvm::StringRef k, T v)
Definition Remarks.h:199
Arg(llvm::StringRef k, llvm::StringRef v)
Definition Remarks.h:182
Arg(llvm::StringRef k, std::string v)
Definition Remarks.h:183
Arg(llvm::StringRef k, const char *v)
Definition Remarks.h:184
bool isLink
Generated RelatedTo argument, distinct from a user-supplied argument.
Definition Remarks.h:179
Attribute getAttribute() const
Get the attribute if present.
Definition Remarks.h:194
bool hasAttribute() const
Check if this arg has an associated attribute.
Definition Remarks.h:191
Arg(llvm::StringRef k, bool b)
Definition Remarks.h:188
std::optional< Attribute > attr
Optional attribute storage for Attribute-based args.
Definition Remarks.h:177