# Remark Infrastructure

Remarks are **structured, human- and machine-readable notes** emitted by the
compiler to communicate:

- What transformations were applied
- What optimizations were missed
- Why certain decisions were made

The **`RemarkEngine`** collects remarks during compilation and routes them to a
pluggable **streamer**. By default, MLIR integrates with LLVM's
[`llvm::remarks`](https://llvm.org/docs/Remarks.html) infrastructure, enabling
you to:

- Stream remarks as passes run
- Serialize to **YAML** or **LLVM Bitstream** 

***

## Overview

- **Opt-in** – Disabled by default; zero overhead unless enabled.
- **Per-context** – Configured on `MLIRContext`.
- **Formats** – LLVM Remark engine (YAML / Bitstream) or custom streamers.
- **Kinds** – `Passed`, `Missed`, `Failure`, `Analysis`.
- **API** – Lightweight streaming interface using `<<` (like MLIR diagnostics).

***

## Architecture

The remark system consists of two main components:

### RemarkEngine

Owned by `MLIRContext`, the engine:

- Receives finalized `InFlightRemark` objects
- Optionally mirrors remarks to the `DiagnosticEngine`
- Dispatches to the installed streamer

### MLIRRemarkStreamerBase

An abstract backend interface with a single hook:

```c++
virtual void streamOptimizationRemark(const Remark &remark) = 0;
```

The default implementation, **`MLIRLLVMRemarkStreamer`**, adapts `mlir::Remark`
to LLVM's remark format and writes YAML or Bitstream via
`llvm::remarks::RemarkStreamer`.

**Ownership chain:** `MLIRContext` → `RemarkEngine` → `MLIRRemarkStreamerBase`

***

## Remark Categories

MLIR provides four built-in categories:

### Passed

An optimization or transformation succeeded.

```
[Passed] RemarkName | Category:Vectorizer:myPass1 | Function=foo | Remark="vectorized loop", tripCount=128
```

### Missed

An optimization didn't apply and produces ideally an actionable feedback.

```
[Missed]  | Category:Unroll | Function=foo | Reason="tripCount=4 < threshold=256", Suggestion="increase unroll to 128"
```

### Failure

An optimization was attempted but failed. Unlike `Missed`, this indicates an
active attempt that couldn't complete.

For example, when a user requests `--use-max-register=100` but the allocator
cannot satisfy the constraint:

```
[Failed] Category:RegisterAllocator | Reason="Limiting to use-max-register=100 failed; it now uses 104 registers for better performance"
```

### Analysis

Neutral informational output—useful for profiling and debugging.

```
[Analysis] Category:Register | Remark="Kernel uses 168 registers"
[Analysis] Category:Register | Remark="Kernel uses 10kB local memory"
```

***

## Emitting Remarks

Use the `remark::*` helpers to create an **in-flight remark**, then append
content with the `<<` operator.

### Configuring Remark Options

Each remark accepts four fields (all `StringRef`):

| Field          | Description                                    |
|***************-|************************************************|
| **Name**       | Identifiable name for the remark               |
| **Category**   | High-level classification                      |
| **Sub-category** | Fine-grained classification                  |
| **Function**   | The function where the remark originates       |

### Basic Example

```c++
#include "mlir/IR/Remarks.h"

LogicalResult MyPass::runOnOperation() {
  Location loc = getOperation()->getLoc();

  auto opts = remark::RemarkOpts::name("VectorizeLoop")
                  .category("Vectorizer")
                  .subCategory("MyPass")
                  .function("foo");

  // Passed: transformation succeeded
  remark::passed(loc, opts)
      << "vectorized loop"
      << remark::metric("tripCount", 128);

  // Analysis: informational output
  remark::analysis(loc, opts)
      << "Kernel uses 168 registers";

  // Missed: optimization skipped (with reason and suggestion)
  remark::missed(loc, opts)
      << remark::reason("tripCount={0} < threshold={1}", 4, 256)
      << remark::suggest("increase unroll factor to {0}", 128);

  // Failure: optimization attempted but failed
  remark::failed(loc, opts)
      << remark::reason("unsupported pattern encountered");

  return success();
}
```

***

## Metrics and Helpers

All helper functions accept
[LLVM format strings](https://llvm.org/docs/ProgrammersManual.html#formatting-strings-the-formatv-function),
which build lazily—ensuring zero cost when remarks are disabled.

| Helper                         | Description                              |
|******************************--|******************************************|
| `remark::metric(key, value)`   | Adds a structured key–value pair         |
| `remark::add(fmt, ...)`        | Shortcut for `metric("Remark", ...)`     |
| `remark::reason(fmt, ...)`     | Shortcut for `metric("Reason", ...)`     |
| `remark::suggest(fmt, ...)`    | Shortcut for `metric("Suggestion", ...)` |

### String Shorthand

Appending a plain string:

```c++
remark::passed(loc, opts) << "vectorized loop";
```

is equivalent to:

```c++
remark::passed(loc, opts) << remark::metric("Remark", "vectorized loop");
```

### Custom Metrics

Add structured data for machine readability:

```c++
remark::passed(loc, opts)
    << "loop optimized"
    << remark::metric("TripCount", 128)
    << remark::metric("VectorWidth", 4);
```

***

## Emitting Policies

The `RemarkEngine` supports pluggable policies that control which remarks are
emitted.

### RemarkEmittingPolicyAll

Emits **all** remarks unconditionally.

### RemarkEmittingPolicyFinal

Emits only the **final** remark for each location. This is useful in multi-pass
compilers where an early pass may report a failure, but a later pass succeeds.

**Example:** Only the successful remark is emitted:

```c++
auto opts = remark::RemarkOpts::name("Unroller").category("LoopUnroll");

// First pass: reports failure
remark::failed(loc, opts) << "Loop could not be unrolled";

// Later pass: reports success (this is the one emitted)
remark::passed(loc, opts) << "Loop unrolled successfully";
```

You can also implement custom policies by inheriting from the policy interface.

***

## Enabling Remarks

### Option 1: LLVM Remark Streamer (YAML or Bitstream)

Persist remarks to a file for post-processing:

```c++
// Setup categories
remark::RemarkCategories cats{
    /*passed=*/   "LoopUnroll",
    /*missed=*/   std::nullopt,
    /*analysis=*/ std::nullopt,
    /*failed=*/   "LoopUnroll"
};

// Use final policy
std::unique_ptr<remark::RemarkEmittingPolicyFinal> policy =
        std::make_unique<remark::RemarkEmittingPolicyFinal>();

remark::enableOptimizationRemarksWithLLVMStreamer(
    context, outputFile, llvm::remarks::Format::YAML, std::move(policy), cats);
```

**YAML output** (human-readable):

```yaml
*** !Passed
pass:     Vectorizer:MyPass
name:     VectorizeLoop
function: foo
loc:      input.mlir:12:3
args:
  - Remark:    vectorized loop
  - tripCount: 128
```

**Bitstream format** — compact binary for large-scale analysis.

### Option 2: Diagnostic Engine (No Streamer)

Mirror remarks to the standard diagnostic output:

```c++
// Setup categories
remark::RemarkCategories cats{
    /*passed=*/   "LoopUnroll",
    /*missed=*/   std::nullopt,
    /*analysis=*/ std::nullopt,
    /*failed=*/   "LoopUnroll"
};

// Use final policy
std::unique_ptr<remark::RemarkEmittingPolicyFinal> policy =
        std::make_unique<remark::RemarkEmittingPolicyFinal>();

remark::enableOptimizationRemarks(
    context,
    /*streamer=*/ nullptr,
    /*policy=*/ std::move(policy),
    cats,
    /*printAsEmitRemarks=*/ true);
```

### Option 3: Custom Streamer

Implement your own backend for specialized output formats:

```c++
class MyStreamer : public MLIRRemarkStreamerBase {
public:
  void streamOptimizationRemark(const Remark &remark) override {
    // Custom serialization logic
  }
};

auto streamer = std::make_unique<MyStreamer>();
remark::enableOptimizationRemarks(context, std::move(streamer), cats);
```
