1818#include " llvm/Remarks/Remark.h"
1919#include " llvm/Support/FormatVariadic.h"
2020#include " llvm/Support/Regex.h"
21- #include < optional>
2221
2322#include " mlir/IR/Diagnostics.h"
2423#include " mlir/IR/MLIRContext.h"
@@ -144,7 +143,7 @@ class Remark {
144143
145144 llvm::StringRef getCategoryName () const { return categoryName; }
146145
147- llvm::StringRef getFullCategoryName () const {
146+ llvm::StringRef getCombinedCategoryName () const {
148147 if (categoryName.empty () && subCategoryName.empty ())
149148 return {};
150149 if (subCategoryName.empty ())
@@ -318,7 +317,7 @@ class InFlightRemark {
318317};
319318
320319// ===----------------------------------------------------------------------===//
321- // MLIR Remark Streamer
320+ // Pluggable Remark Utilities
322321// ===----------------------------------------------------------------------===//
323322
324323// / Base class for MLIR remark streamers that is used to stream
@@ -338,6 +337,26 @@ class MLIRRemarkStreamerBase {
338337 virtual void finalize () {} // optional
339338};
340339
340+ using ReportFn = llvm::unique_function<void (const Remark &)>;
341+
342+ // / Base class for MLIR remark emitting policies that is used to emit
343+ // / optimization remarks to the underlying remark streamer. The derived classes
344+ // / should implement the `reportRemark` method to provide the actual emitting
345+ // / implementation.
346+ class RemarkEmittingPolicyBase {
347+ protected:
348+ ReportFn reportImpl;
349+
350+ public:
351+ RemarkEmittingPolicyBase () = default ;
352+ virtual ~RemarkEmittingPolicyBase () = default ;
353+
354+ void initialize (ReportFn fn) { reportImpl = std::move (fn); }
355+
356+ virtual void reportRemark (const Remark &remark) = 0;
357+ virtual void finalize () = 0;
358+ };
359+
341360// ===----------------------------------------------------------------------===//
342361// Remark Engine (MLIR Context will own this class)
343362// ===----------------------------------------------------------------------===//
@@ -355,6 +374,8 @@ class RemarkEngine {
355374 std::optional<llvm::Regex> failedFilter;
356375 // / The MLIR remark streamer that will be used to emit the remarks.
357376 std::unique_ptr<MLIRRemarkStreamerBase> remarkStreamer;
377+ // / The MLIR remark policy that will be used to emit the remarks.
378+ std::unique_ptr<RemarkEmittingPolicyBase> remarkEmittingPolicy;
358379 // / When is enabled, engine also prints remarks as mlir::emitRemarks.
359380 bool printAsEmitRemarks = false ;
360381
@@ -392,6 +413,8 @@ class RemarkEngine {
392413 InFlightRemark emitIfEnabled (Location loc, RemarkOpts opts,
393414 bool (RemarkEngine::*isEnabled)(StringRef)
394415 const );
416+ // / Report a remark.
417+ void reportImpl (const Remark &remark);
395418
396419public:
397420 // / Default constructor is deleted, use the other constructor.
@@ -407,8 +430,15 @@ class RemarkEngine {
407430 ~RemarkEngine ();
408431
409432 // / Setup the remark engine with the given output path and format.
410- LogicalResult initialize (std::unique_ptr<MLIRRemarkStreamerBase> streamer,
411- std::string *errMsg);
433+ LogicalResult
434+ initialize (std::unique_ptr<MLIRRemarkStreamerBase> streamer,
435+ std::unique_ptr<RemarkEmittingPolicyBase> remarkEmittingPolicy,
436+ std::string *errMsg);
437+
438+ // / Get the remark emitting policy.
439+ RemarkEmittingPolicyBase *getRemarkEmittingPolicy () const {
440+ return remarkEmittingPolicy.get ();
441+ }
412442
413443 // / Report a remark.
414444 void report (const Remark &&remark);
@@ -446,6 +476,46 @@ inline InFlightRemark withEngine(Fn fn, Location loc, Args &&...args) {
446476
447477namespace mlir ::remark {
448478
479+ // ===----------------------------------------------------------------------===//
480+ // Remark Emitting Policies
481+ // ===----------------------------------------------------------------------===//
482+
483+ // / Policy that emits all remarks.
484+ class RemarkEmittingPolicyAll : public detail ::RemarkEmittingPolicyBase {
485+ public:
486+ RemarkEmittingPolicyAll ();
487+
488+ void reportRemark (const detail::Remark &remark) override {
489+ assert (reportImpl && " reportImpl is not set" );
490+ reportImpl (remark);
491+ }
492+ void finalize () override {}
493+ };
494+
495+ // / Policy that emits final remarks.
496+ class RemarkEmittingPolicyFinal : public detail ::RemarkEmittingPolicyBase {
497+ private:
498+ // / user can intercept them for custom processing via a registered callback,
499+ // / otherwise they will be reported on engine destruction.
500+ llvm::DenseSet<detail::Remark> postponedRemarks;
501+
502+ public:
503+ RemarkEmittingPolicyFinal ();
504+
505+ void reportRemark (const detail::Remark &remark) override {
506+ postponedRemarks.erase (remark);
507+ postponedRemarks.insert (remark);
508+ }
509+
510+ void finalize () override {
511+ assert (reportImpl && " reportImpl is not set" );
512+ for (auto &remark : postponedRemarks) {
513+ if (reportImpl)
514+ reportImpl (remark);
515+ }
516+ }
517+ };
518+
449519// / Create a Reason with llvm::formatv formatting.
450520template <class ... Ts>
451521inline detail::LazyTextBuild reason (const char *fmt, Ts &&...ts) {
@@ -505,16 +575,72 @@ inline detail::InFlightRemark analysis(Location loc, RemarkOpts opts) {
505575
506576// / Setup remarks for the context. This function will enable the remark engine
507577// / and set the streamer to be used for optimization remarks. The remark
508- // / categories are used to filter the remarks that will be emitted by the remark
509- // / engine. If a category is not specified, it will not be emitted. If
578+ // / categories are used to filter the remarks that will be emitted by the
579+ // / remark engine. If a category is not specified, it will not be emitted. If
510580// / `printAsEmitRemarks` is true, the remarks will be printed as
511581// / mlir::emitRemarks. 'streamer' must inherit from MLIRRemarkStreamerBase and
512582// / will be used to stream the remarks.
513583LogicalResult enableOptimizationRemarks (
514584 MLIRContext &ctx,
515585 std::unique_ptr<remark::detail::MLIRRemarkStreamerBase> streamer,
586+ std::unique_ptr<remark::detail::RemarkEmittingPolicyBase>
587+ remarkEmittingPolicy,
516588 const remark::RemarkCategories &cats, bool printAsEmitRemarks = false );
517589
518590} // namespace mlir::remark
519591
592+ // DenseMapInfo specialization for Remark
593+ namespace llvm {
594+ template <>
595+ struct DenseMapInfo <mlir::remark::detail::Remark> {
596+ static constexpr StringRef kEmptyKey = " <EMPTY_KEY>" ;
597+ static constexpr StringRef kTombstoneKey = " <TOMBSTONE_KEY>" ;
598+
599+ // / Helper to provide a static dummy context for sentinel keys.
600+ static mlir::MLIRContext *getStaticDummyContext () {
601+ static mlir::MLIRContext dummyContext;
602+ return &dummyContext;
603+ }
604+
605+ // / Create an empty remark
606+ static inline mlir::remark::detail::Remark getEmptyKey () {
607+ return mlir::remark::detail::Remark (
608+ mlir::remark::RemarkKind::RemarkUnknown, mlir::DiagnosticSeverity::Note,
609+ mlir::UnknownLoc::get (getStaticDummyContext ()),
610+ mlir::remark::RemarkOpts::name (kEmptyKey ));
611+ }
612+
613+ // / Create a dead remark
614+ static inline mlir::remark::detail::Remark getTombstoneKey () {
615+ return mlir::remark::detail::Remark (
616+ mlir::remark::RemarkKind::RemarkUnknown, mlir::DiagnosticSeverity::Note,
617+ mlir::UnknownLoc::get (getStaticDummyContext ()),
618+ mlir::remark::RemarkOpts::name (kTombstoneKey ));
619+ }
620+
621+ // / Compute the hash value of the remark
622+ static unsigned getHashValue (const mlir::remark::detail::Remark &remark) {
623+ return llvm::hash_combine (
624+ remark.getLocation ().getAsOpaquePointer (),
625+ llvm::hash_value (remark.getRemarkName ()),
626+ llvm::hash_value (remark.getCombinedCategoryName ()));
627+ }
628+
629+ static bool isEqual (const mlir::remark::detail::Remark &lhs,
630+ const mlir::remark::detail::Remark &rhs) {
631+ // Check for empty/tombstone keys first
632+ if (lhs.getRemarkName () == kEmptyKey ||
633+ lhs.getRemarkName () == kTombstoneKey ||
634+ rhs.getRemarkName () == kEmptyKey ||
635+ rhs.getRemarkName () == kTombstoneKey ) {
636+ return lhs.getRemarkName () == rhs.getRemarkName ();
637+ }
638+
639+ // For regular remarks, compare key identifying fields
640+ return lhs.getLocation () == rhs.getLocation () &&
641+ lhs.getRemarkName () == rhs.getRemarkName () &&
642+ lhs.getCombinedCategoryName () == rhs.getCombinedCategoryName ();
643+ }
644+ };
645+ } // namespace llvm
520646#endif // MLIR_IR_REMARKS_H
0 commit comments