[Mlir-commits] [mlir] [MLIR] Introduce RemarkEngine + pluggable remark streaming (YAML/Bitstream) (PR #152474)

Guray Ozen llvmlistbot at llvm.org
Fri Aug 15 04:40:13 PDT 2025


================
@@ -0,0 +1,452 @@
+//===- Remarks.h - MLIR Optimization Remark ----------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines utilities for emitting optimization remarks.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_IR_REMARKS_H
+#define MLIR_IR_REMARKS_H
+
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/Remarks/Remark.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/Regex.h"
+#include <optional>
+
+#include "mlir/IR/Diagnostics.h"
+#include "mlir/IR/MLIRContext.h"
+#include "mlir/IR/Value.h"
+
+namespace mlir::remark {
+/// Define an the set of categories to accept.
+/// By default none are, the provided regex matches against
+/// the category names for each kind of remark.
+struct RemarkCategories {
+  std::optional<std::string> passed, missed, analysis, failed;
+};
+
+/// Defines different remark kinds that can be used to categorize remarks.
+enum class RemarkKind {
+  OptimizationRemarkUnknown = 0,
+  OptimizationRemarkPassed,   // Optimization remark that was passed.
+  OptimizationRemarkMissed,   // Optimization remark that was missed.
+  OptimizationRemarkFailure,  // Optimization failure remark.
+  OptimizationRemarkAnalysis, // Analysis remark that does not indicate a pass.
+};
+} // namespace mlir::remark
+
+namespace mlir::remark::detail {
+//===----------------------------------------------------------------------===//
+// Remark Base Class
+//===----------------------------------------------------------------------===//
+class Remark {
+
+public:
+  Remark(RemarkKind remarkKind, DiagnosticSeverity severity,
+         const char *passName, StringRef remarkName, Location loc,
+         std::optional<StringRef> functionName = std::nullopt)
+      : remarkKind(remarkKind), functionName(functionName), loc(loc),
+        passName(passName), remarkName(remarkName) {}
+
+  // Remark argument that is a key-value pair that can be printed as machine
+  // parsable args.
+  struct Arg {
+    std::string key;
+    std::string val;
+    Arg(llvm::StringRef m) : key("Remark"), val(m) {}
+    Arg(llvm::StringRef k, llvm::StringRef v) : key(k), val(v) {}
+    Arg(llvm::StringRef k, std::string v) : key(k), val(std::move(v)) {}
+    Arg(llvm::StringRef k, const char *v) : Arg(k, llvm::StringRef(v)) {}
+    Arg(llvm::StringRef k, Value v);
+    Arg(llvm::StringRef k, Type t);
+    Arg(llvm::StringRef k, bool b) : key(k), val(b ? "true" : "false") {}
+
+    // One constructor for all arithmetic types except bool.
+    template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T> &&
+                                                      !std::is_same_v<T, bool>>>
+    Arg(llvm::StringRef k, T v) : key(k) {
+      if constexpr (std::is_floating_point_v<T>) {
+        llvm::raw_string_ostream os(val);
+        os << v;
+      } else if constexpr (std::is_signed_v<T>) {
+        val = llvm::itostr(static_cast<long long>(v));
+      } else {
+        val = llvm::utostr(static_cast<unsigned long long>(v));
+      }
+    }
+  };
+
+  void insert(llvm::StringRef s);
+  void insert(Arg a);
+
+  void print(llvm::raw_ostream &os, bool printLocation = false) const;
+
+  Location getLocation() const { return loc; }
+  /// Diagnostic -> Remark
+  llvm::remarks::Remark generateRemark() const;
+
+  StringRef getFunction() const {
+    if (functionName)
+      return *functionName;
+    return "<unknown function>";
+  }
+  StringRef getPassName() const { return passName; }
+  StringRef getRemarkName() const { return remarkName; }
+  std::string getMsg() const;
+
+  ArrayRef<Arg> getArgs() const { return args; }
+
+  llvm::remarks::Type getRemarkType() const;
+
+  std::string getRemarkTypeString() const;
+
+protected:
+  /// Keeps the MLIR diagnostic kind, which is used to determine the
+  /// diagnostic kind in the LLVM remark streamer.
+  RemarkKind remarkKind;
+  /// Name of the convering function like interface
+  std::optional<std::string> functionName;
+
+  Location loc;
+  /// Name of the pass that triggers this report.
+  const char *passName;
+
+  /// Textual identifier for the remark (single-word, CamelCase). Can be used
+  /// by external tools reading the output file for optimization remarks to
+  /// identify the remark.
+  StringRef remarkName;
+
+  /// Args collected via the streaming interface.
+  SmallVector<Arg, 4> args;
+
+private:
+  /// Convert the MLIR diagnostic severity to LLVM diagnostic severity.
+  static llvm::DiagnosticSeverity
+  makeLLVMSeverity(DiagnosticSeverity severity) {
+    switch (severity) {
+    case DiagnosticSeverity::Note:
+      return llvm::DiagnosticSeverity::DS_Note;
+    case DiagnosticSeverity::Warning:
+      return llvm::DiagnosticSeverity::DS_Warning;
+    case DiagnosticSeverity::Error:
+      return llvm::DiagnosticSeverity::DS_Error;
+    case DiagnosticSeverity::Remark:
+      return llvm::DiagnosticSeverity::DS_Remark;
+    }
+    llvm_unreachable("Unknown diagnostic severity");
+  }
+  /// Convert the MLIR remark kind to LLVM diagnostic kind.
+  static llvm::DiagnosticKind makeLLVMKind(RemarkKind remarkKind) {
+    switch (remarkKind) {
+    case RemarkKind::OptimizationRemarkUnknown:
+      return llvm::DiagnosticKind::DK_Generic;
+    case RemarkKind::OptimizationRemarkPassed:
+      return llvm::DiagnosticKind::DK_OptimizationRemark;
+    case RemarkKind::OptimizationRemarkMissed:
+      return llvm::DiagnosticKind::DK_OptimizationRemarkMissed;
+    case RemarkKind::OptimizationRemarkFailure:
+      return llvm::DiagnosticKind::DK_OptimizationFailure;
+    case RemarkKind::OptimizationRemarkAnalysis:
+      return llvm::DiagnosticKind::DK_OptimizationRemarkAnalysis;
+    }
+    llvm_unreachable("Unknown diagnostic kind");
+  }
+};
+
+inline Remark &operator<<(Remark &r, StringRef s) {
+  r.insert(s);
+  return r;
+}
+inline Remark &&operator<<(Remark &&r, StringRef s) {
+  r.insert(s);
+  return std::move(r);
+}
+inline Remark &operator<<(Remark &r, const Remark::Arg &kv) {
+  r.insert(kv);
+  return r;
+}
+
+//===----------------------------------------------------------------------===//
+// Shorthand aliases for different kinds of remarks.
+//===----------------------------------------------------------------------===//
+
+template <RemarkKind K, DiagnosticSeverity S>
+class OptRemarkBase final : public Remark {
+public:
+  explicit OptRemarkBase(Location loc, StringRef passName,
+                         StringRef categoryName)
+      : Remark(K, S, passName.data(), categoryName, loc) {}
+};
+
+using OptRemarkAnalysis = OptRemarkBase<RemarkKind::OptimizationRemarkAnalysis,
+                                        DiagnosticSeverity::Remark>;
+
+using OptRemarkPass = OptRemarkBase<RemarkKind::OptimizationRemarkPassed,
+                                    DiagnosticSeverity::Remark>;
+
+using OptRemarkMissed = OptRemarkBase<RemarkKind::OptimizationRemarkMissed,
+                                      DiagnosticSeverity::Remark>;
+
+using OptRemarkFailure = OptRemarkBase<RemarkKind::OptimizationRemarkFailure,
+                                       DiagnosticSeverity::Remark>;
+
+class RemarkEngine;
+
+//===----------------------------------------------------------------------===//
+// InFlightRemark
+//===----------------------------------------------------------------------===//
+
+/// Lazy text building for zero cost  string formatting.
+struct LazyTextBuild {
----------------
grypp wrote:

I tried using `llvm::formatv`, but it isn’t zero-cost. The string is built even when remarks are disabled. I switched to a callback instead so I've put `LazyTextBuild`. 

https://github.com/llvm/llvm-project/pull/152474


More information about the Mlir-commits mailing list