2040 Commits

Author SHA1 Message Date
Guray Ozen
3d41197d68
[MLIR] Introduce RemarkEngine + pluggable remark streaming (YAML/Bitstream) (#152474)
This PR implements structured, tooling-friendly optimization remarks
with zero cost unless enabled. It implements:
- `RemarkEngine` collects finalized remarks within `MLIRContext`.
- `MLIRRemarkStreamerBase` abstract class streams them to a backend.
- Backends: `MLIRLLVMRemarkStreamer` (bridges to llvm::remarks →
YAML/Bitstream) or your own custom streamer.
- Optional mirroring to DiagnosticEngine (printAsEmitRemarks +
categories).
- Off by default; no behavior change unless enabled. Thread-safe;
ordering best-effort.


## Overview

```
Passes (reportOptimization*)
         │
         ▼
+-------------------+
|  RemarkEngine     |   collects
+-------------------+
     │         │
     │ mirror  │ stream
     ▼         ▼
emitRemark    MLIRRemarkStreamerBase (abstract)
                   │
                   ├── MLIRLLVMRemarkStreamer → llvm::remarks → YAML | Bitstream
                   └── CustomStreamer → your sink
```

## Enable Remark engine and Plug LLVM's Remark streamer
```
// Enable once per MLIRContext. This uses `MLIRLLVMRemarkStreamer`
mlir::remark::enableOptimizationRemarksToFile(
    ctx, path, llvm::remarks::Format::YAML, cats);
```

## API to emit remark
```
// Emit from a pass
 remark::passed(loc, categoryVectorizer, myPassname1)
        << "vectorized loop";

remark::missed(loc, categoryUnroll, "MyPass")
        << remark::reason("not profitable at this size")   // Creates structured reason arg
        << remark::suggest("increase unroll factor to >=4");   // Creates structured suggestion arg

remark::passed(loc, categoryVectorizer, myPassname1)
        << "vectorized loop" 
        << remark::metric("tripCount", 128);                // Create structured metric on-the-fly
```
2025-08-21 16:02:31 +02:00
Mehdi Amini
acda808304
[MLIR] Adopt LDBG() macro in BuiltinAttributes.cpp (NFC) (#154723) 2025-08-21 10:31:18 +00:00
Mehdi Amini
db0529dca3
[MLIR] Use LDBG() macro in Dialect.cpp (NFC) (#154720) 2025-08-21 10:28:51 +00:00
Mehdi Amini
6445a75c98
[MLIR] Update MLIRContext to use the LDBG() style debug macro (NFC) (#154619) 2025-08-20 21:30:11 +00:00
Matthias Springer
6a285cc8e6
[mlir][IR] Fix Block::without_terminator for blocks without terminator (#154498)
Blocks without a terminator are not handled correctly by
`Block::without_terminator`: the last operation is excluded, even when
it is not a terminator. With this commit, only terminators are excluded.
If the last operation is unregistered, it is included for safety.
2025-08-20 18:02:24 +02:00
Boyana Norris
1eaf736384
[mlir] Clone attrs of unregistered dialect ops (#151847)
`Operation::clone` does not clone the properties of unregistered ops.
This patch modifies the property initialization for unregistered ops to
initialize properties as attributes.

fixes #151640

---------

Signed-off-by: Boyana Norris <brnorris03@gmail.com>
2025-08-05 08:16:14 +02:00
Mehdi Amini
e8e9bef32b
[MLIR] Use LDBG in MLIR AsmPrinter (#151163) 2025-07-30 17:56:34 +02:00
Jacques Pienaar
b6a98b934f
[mlir] Report line number from file rather than split (#150982)
Add convention for lexer if the last file is contained in the first,
then the first is used for error reporting. This requires that these two
overlap to make it easy to find the corresponding spots. Enables going
from

```
within split at mlir/test/IR/invalid.mlir::10 offset :6:9: error: reference to an undefined block
```

to

```
mlir/test/IR/invalid.mlir:15:9: error: reference to an undefined block
```

This does change the split to not produce always null terminated buffers
and tools that need it, need to do so themselves (which is mostly by copying -
this may have little actual impact as previously this was a copy too).
2025-07-29 13:29:00 +02:00
Matthias Springer
a7c9563995
[mlir][IR] Set insertion point when erasing an operation (#146955)
Erasing the operation to which the current insertion point is set,
leaves the insertion point in an invalid state. This commit resets the
insertion point to the following operation.

Also adjust the insertion point when inlining a block.
2025-07-27 10:27:27 +02:00
Mehdi Amini
2f8c926d6e
[MLIR] Migrate PatternLoggingListener to the standard LDBG output (#150686) 2025-07-25 21:51:07 +02:00
Kazu Hirata
1a0f482de8
[mlir] Remove unused includes (NFC) (#150476)
These are identified by misc-include-cleaner.  I've filtered out those
that break builds.  Also, I'm staying away from llvm-config.h,
config.h, and Compiler.h, which likely cause platform- or
compiler-specific build failures.
2025-07-24 11:23:53 -07:00
Longsheng Mou
3eb49c482c
[mlir][NFC] Use hasOneBlock instead of llvm::hasSingleElement(region) (#149809) 2025-07-24 10:11:21 +08:00
Maksim Levental
2736fbd832
[mlir][NFC] update mlir/lib create APIs (26/n) (#149933)
See https://github.com/llvm/llvm-project/pull/147168 for more info.

---------

Co-authored-by: Tobias Gysi <tobias.gysi@nextsilicon.com>
2025-07-22 08:40:42 -04:00
Jeremy Kun
7caf12da0b
[mlir][core] Add an MLIR "pattern catalog" generator (#146228)
This PR adds a feature that attaches a listener to all RewritePatterns that
logs information about the modified operations.

When the MLIR test suite is run, these debug outputs can
be filtered and combined into an index linking operations to the
patterns that insert, modify, or replace them. This index is intended to
be used to create a website that allows one to look up patterns from an
operation name.

The debug logs emitted can be viewed with --debug-only=generate-pattern-catalog, 
and the lit config is modified to do this when the env var MLIR_GENERATE_PATTERN_CATALOG is set.

Example usage:

```
mkdir build && cd build
cmake -G Ninja ../llvm \
  -DLLVM_ENABLE_PROJECTS="mlir" \
  -DLLVM_TARGETS_TO_BUILD="host" \
  -DCMAKE_BUILD_TYPE=DEBUG
ninja -j 24 check-mlir
MLIR_GENERATE_PATTERN_CATALOG=1 bin/llvm-lit -j 24 -v -a tools/mlir/test | grep 'pattern-logging-listener' | sed 's/^# | [pattern-logging-listener] //g' | sort | uniq > pattern_catalog.txt
```

Sample pattern catalog output (that fits in a gist):
https://gist.github.com/j2kun/02d1ab8d31c10d71027724984c89905a

---------

Co-authored-by: Jeremy Kun <j2kun@users.noreply.github.com>
Co-authored-by: Mehdi Amini <joker.eph@gmail.com>
2025-07-17 09:09:12 -07:00
Artemiy Bulavin
38be53aa04
[MLIR] Fix use-after-frees when accessing DistinctAttr storage (#148666)
This PR fixes a use-after-free error that happens when `DistinctAttr`
instances are created within a `PassManager` running with crash recovery
enabled. The root cause is that `DistinctAttr` storage is allocated in a
thread_local allocator, which is destroyed when the crash recovery
thread joins, invalidating the storage.

Moreover, even without crash reproduction disabling multithreading on
the context will destroy the context's thread pool, and in turn delete
the threadlocal storage. This means a call to
`ctx->disableMulthithreading()` breaks the IR.

This PR replaces the thread local allocator with a synchronised
allocator that's shared between threads. This persists the lifetime of
allocated DistinctAttr storage instances to the lifetime of the context.

### Problem Details:

The `DistinctAttributeAllocator` uses a
`ThreadLocalCache<BumpPtrAllocator>` for lock-free allocation of
`DistinctAttr` storage in a multithreaded context. The issue occurs when
a `PassManager` is run with crash recovery (`runWithCrashRecovery`), the
pass pipeline is executed on a temporary thread spawned by
`llvm::CrashRecoveryContext`. Any `DistinctAttr`s created during this
execution have their storage allocated in the thread_local cache of this
temporary thread. When the thread joins, the thread_local storage is
destroyed, freeing the `DistinctAttr`s' memory. If this attribute is
accessed later, e.g. when printing, it results in a use-after-free.

As mentioned previously, this is also seen after creating some
`DistinctAttr`s and then calling `ctx->disableMulthithreading()`.

### Solution

`DistinctAttrStorageAllocator` uses a synchronised, shared allocator
instead of one wrapped in a `ThreadLocalCache`. The former is what
stores the allocator in transient thread_local storage.

### Testing:

A C++ unit test has been added to validate this fix. (I was previously
reproducing this failure with `mlir-opt` but I can no longer do so and I
am unsure why.)

-----

Note: This is a 2nd attempt at my previous PR
https://github.com/llvm/llvm-project/pull/128566 that was reverted in
https://github.com/llvm/llvm-project/pull/133000. I believe I've
addressed the TSAN and race condition concerns.
2025-07-16 12:11:38 +02:00
Jakub Kuderski
6512ca7ddb
[mlir] Add isStatic* size check for ShapedTypes. NFCI. (#147085)
The motivation is to avoid having to negate `isDynamic*` checks, avoid
double negations, and allow for `ShapedType::isStaticDim` to be used in
ADT functions without having to wrap it in a lambda performing the
negation.

Also add the new functions to C and Python bindings.
2025-07-07 14:57:27 -04:00
Longsheng Mou
5a8e60e724
[mlir] Use llvm::fill instead of std::fill(NFC) (#146889) 2025-07-07 09:12:38 +08:00
Mehdi Amini
ca297cd6e4
[MLIR] Add support for IntArrayProp<I32Prop> (#146685)
The conversion to attribute was missing.
2025-07-06 11:55:02 +02:00
Ivan Butygin
454e4e3e29
[mlir][AffineExpr] Order arguments in the commutative affine exprs (#146895)
Order symbol/dim arguments by position and put dims before symbols. This
is to help affine simplifications.
2025-07-04 23:34:07 +03:00
Kazu Hirata
e8f491fc97
[mlir] Remove unused includes (NFC) (#146812) 2025-07-03 09:08:09 -07:00
Mehdi Amini
6ec9b1b366
[MLIR] Remove spurious space when printing prop-dict (#145962)
When there is an elided properties, there use to be an extra space
insert in the prop-dict printing before the dictionnary.

Fix #145695
2025-07-02 14:07:17 +02:00
XiangZhang
aa1d9a4c31
[MLIR][Affine] Enhance simplifyAdd for AffineExpr mod (#146492)
Currently AffineExpr Add has ability to optimize `"s1 + (s1 // c * -c)"
to "s1 % c"`,
but can not optimize `"(s0 + s1) + (s1 // c * -c)"`. 
This patch provide an opportunity to do this simplification, let it can
be simplified to `"s0 + s1 % c"`.
2025-07-02 11:08:58 +08:00
Kazu Hirata
9d6cbc3c20
[ADT] Deprecate MutableArrayRef(std::nullopt) (#146113)
ArrayRef(std::nullopt) just got deprecated.  This patch does the same
to MutableArrayRef(std::nullopt).  Since there are only a couple of
uses, this patch does migration and deprecation at the same time.
2025-06-27 11:31:11 -07:00
Jacques Pienaar
d0469d1d3c
[mlir] Move WalkResult to Support (#145649)
This also enables moving StateStack, both are relatively generic helper
structs not tied to IR.
2025-06-25 01:58:44 -07:00
Lance Wang
77af8bff97
[mlir]Moves the StateStack to IR folder from Support folder. (#145598)
[MLIR] Fix circular dependency introduced in In
https://github.com/llvm/llvm-project/pull/144897. This PR is to break
the dependency. by moving StateStack to IR folder

This commit resolves a circular dependency issue between mlir/Support
and mlir/IR:

- Move StateStack.h and StateStack.cpp from Support to IR folder
- Update CMakeLists.txt files to reflect the new locations
- Update Bazel BUILD file to maintain correct dependencies
- Update includes in affected files (flang, Target/LLVMIR)

The circular dependency was caused by StateStack.h depending on
IR/Visitors.h
while other IR files depended on Support. Moving StateStack to IR
eliminates
this cycle while maintaining proper separation of concerns.
2025-06-25 00:00:13 -04:00
Mehdi Amini
b0366eeb7e
[MLIR] Add support for int8/uint8 properties (#145019)
This patch is adding the ability to print a uint8_t/int8_t as an int
instead of a char and demonstrate support for int8_t/uin8_t properties.

Fix #144993
2025-06-23 16:57:14 +02:00
Momchil Velikov
4af96a9d83
[MLIR] Determine contiguousness of memrefs with dynamic dimensions (#142421)
This patch enhances `MemRefType::areTrailingDimsContiguous` to also
handle memrefs with dynamic dimensions.

The implementation itself is based on a new member function
`MemRefType::getMaxCollapsableTrailingDims` that return the maximum
number of trailing dimensions that can be collapsed - trivially all
dimensions for memrefs with identity layout, or by examining the memref
strides stopping at discontiguous or statically unknown strides.
2025-06-23 09:28:33 +01:00
Andrei Golubev
529662a6b5
[mlir] Allow accessing DialectResourceBlobManager::blobMap (#142352)
Add a new API to access all blobs that are stored in the blob manager.
The main purpose (as of now) is to allow users of dialect resources to
iterate over all blobs, especially when the blobs are no longer used in
IR (e.g. the operation that uses the blob is deleted) and thus cannot be
easily accessed without manual tracking of keys.
2025-06-23 09:50:28 +02:00
Longsheng Mou
b00ddce731
[mlir][affine] Fix a crash when cast incompatible type (#145162)
This PR fixes a crash in `getSemiAffineExprFromFlatForm` when localExpr
is not `AffineBinaryOpExpr`. Fixes #144091.
2025-06-23 09:38:00 +08:00
Evan Liu
6ae5b89553
Make getStridesAndOffset const (#145148)
Make getStridesAndOffset const.
2025-06-22 11:21:47 +02:00
Fabian Mora
f159774352
[mlir][core|ptr] Add PtrLikeTypeInterface and casting ops to the ptr dialect (#137469)
This patch adds the `PtrLikeTypeInterface` type interface to identify
pointer-like types. This interface is defined as:

```
A ptr-like type represents an object storing a memory address. This object
is constituted by:
- A memory address called the base pointer. This pointer is treated as a
  bag of bits without any assumed structure. The bit-width of the base
  pointer must be a compile-time constant. However, the bit-width may remain
  opaque or unavailable during transformations that do not depend on the
  base pointer. Finally, it is considered indivisible in the sense that as
  a `PtrLikeTypeInterface` value, it has no metadata.
- Optional metadata about the pointer. For example, the size of the  memory
  region associated with the pointer.

Furthermore, all ptr-like types have two properties:
- The memory space associated with the address held by the pointer.
- An optional element type. If the element type is not specified, the
  pointer is considered opaque.
```

This patch adds this interface to `!ptr.ptr` and the `memref` type.

Furthermore, this patch adds necessary ops and type to handle casting
between `!ptr.ptr` and ptr-like types.

First, it defines the `!ptr.ptr_metadata` type. An opaque type to
represent the metadata of a ptr-like type. The rationale behind adding
this type, is that at high-level the metadata of a type like `memref`
cannot be specified, as its structure is tied to its lowering.

The `ptr.get_metadata` operation was added to extract the opaque pointer
metadata. The concrete structure of the metadata is only known when the
op is lowered.

Finally, this patch adds the `ptr.from_ptr` and `ptr.to_ptr` operations.
Allowing to cast back and forth between `!ptr.ptr` and ptr-like types.

```mlir
func.func @func(%mr: memref<f32, #ptr.generic_space>) -> memref<f32, #ptr.generic_space> {
  %ptr = ptr.to_ptr %mr : memref<f32, #ptr.generic_space> -> !ptr.ptr<#ptr.generic_space>
  %mda = ptr.get_metadata %mr : memref<f32, #ptr.generic_space>
  %res = ptr.from_ptr %ptr metadata %mda : !ptr.ptr<#ptr.generic_space> -> memref<f32, #ptr.generic_space>
  return %res : memref<f32, #ptr.generic_space>
}
```

It's future work to replace and remove the `bare-ptr-convention` through
the use of these ops.

---------

Co-authored-by: Mehdi Amini <joker.eph@gmail.com>
2025-06-20 14:23:39 -04:00
Kazu Hirata
43c35e858c
[mlir] Simplify calls to *Map::{insert,try_emplace} (NFC) (#143729)
This patch simplifies code by removing the values from
insert/try_emplace.  Note that default values inserted by try_emplace
are immediately overrideen in all these cases.
2025-06-11 12:50:35 -07:00
Umang Yadav
7f08503a3b
Introduce arith.scaling_extf and arith.scaling_truncf (#141965)
This PR adds `arith.scaling_truncf` and `arith.scaling_extf` operations
which supports the block quantization following OCP MXFP specs listed
here
https://www.opencompute.org/documents/ocp-microscaling-formats-mx-v1-0-spec-final-pdf

OCP MXFP Spec comes with reference implementation here
https://github.com/microsoft/microxcaling/tree/main

Interesting piece of reference code is this method `_quantize_mx`
7bc41952de/mx/mx_ops.py (L173).

Both `arith.scaling_truncf` and `arith.scaling_extf` are designed to be
an elementwise operation. Please see description about them in
`ArithOps.td` file for more details.
 
Internally, 

`arith.scaling_truncf` does the
`arith.truncf(arith.divf(input/(2^scale)))`. `scale` should have
necessary broadcast, clamping, normalization and NaN propagation done
before callling into `arith.scaling_truncf`.

`arith.scaling_extf` does the `arith.mulf(2^scale, input)` after taking
care of necessary data type conversions.


CC: @krzysz00 @dhernandez0 @bjacob @pashu123 @MaheshRavishankar
@tgymnich

---------

Co-authored-by: Prashant Kumar <pk5561@gmail.com>
Co-authored-by: Krzysztof Drewniak <Krzysztof.Drewniak@amd.com>
2025-06-09 13:13:31 -05:00
Kazu Hirata
b3b8a097fe
[mlir] Use *Map::try_emplace (NFC) (#143341)
- try_emplace(Key) is shorter than insert({Key, nullptr}).
- try_emplace performs value initialization without value parameters.
- We overwrite values on successful insertion anyway.
2025-06-09 07:18:26 -07:00
Aviad Cohen
4c6449044a
[mlir]: Added properties/attributes ignore flags to OperationEquivalence (#142623)
Those flags are useful for cases and operation which we may consider equivalent even when their attributes/properties are not the same.
2025-06-04 10:01:20 +03:00
Vitaly Buka
60250c15e0
Revert "[mlir]: Added properties/attributes ignore flags to OperationEquivalence" (#142319)
Reverts llvm/llvm-project#141664

See
https://github.com/llvm/llvm-project/pull/141664#issuecomment-2927867604
2025-06-01 13:46:18 -07:00
Aviad Cohen
c5f3018668
[mlir]: Added properties/attributes ignore flags to OperationEquivalence (#141664)
Those flags are useful for cases and operation which we may consider
equivalent even when their attributes/properties are not the same.
2025-05-30 22:18:07 +03:00
Michael Maitland
7454098a9e
[mlir][Value] Add getNumUses, hasNUses, and hasNUsesOrMore to Value (#142084)
We already have hasOneUse. Like llvm::Value we provide helper methods to
query the number of uses of a Value. Add unittests for Value, because
that was missing.

---------

Co-authored-by: Michael Maitland <michaelmaitland@meta.com>
2025-05-30 00:39:45 -04:00
Kazu Hirata
8c55d0fb7e
[mlir] Use llvm::lower_bound (NFC) (#141386) 2025-05-25 08:21:33 -07:00
Kazu Hirata
f3d9dff245
[mlir] Use llvm::less_second (NFC) (#141350) 2025-05-24 09:39:32 -07:00
qazwsxedcrfvtg14
d5802c30ae
[mlir] Optimize const values AffineMap::compose (#141005)
The original implementation will create two intermediate AffineMap in
the context, calling this compose function with different values
multiple times will occupy a lot of memory.

To improve the performance, we can call the AffineExpr::replace
directly, so we don't need to store all combinations of values in the
context.
2025-05-23 17:30:48 -07:00
Kazu Hirata
6464238dc0
[mlir] Use llvm::stable_sort (NFC) (#141186) 2025-05-22 22:36:32 -07:00
Kazu Hirata
6074d83664
[mlir] Remove unused local variables (NFC) (#140990) 2025-05-21 20:33:53 -07:00
Max Graey
8aaac80ddd
[NFC] Use more isa and isa_and_nonnull instead dyn_cast for predicates (#137393)
Also fix some typos in comments

---------

Co-authored-by: Mehdi Amini <joker.eph@gmail.com>
2025-05-13 22:34:42 +08:00
Rahul Joshi
86c5112409
[NFCI][LLVM/MLIR] Adopt TrailingObjects convenience API (#138554)
Adopt `TrailingObjects` convenience API that was added in
https://github.com/llvm/llvm-project/pull/138970 in LLVM and MLIR code.
2025-05-12 16:17:43 -07:00
Rahul Joshi
7245e21e89
[NFC][Support] Add llvm::uninitialized_copy (#138174)
Add `llvm::uninitialized_copy` that accepts a range instead of start/end
iterator for the source of the copy.
2025-05-07 17:37:38 -07:00
Mehdi Amini
c02aa91939
Revert "[mlir][MemRef] Remove integer address space builders" (#138853)
Reverts llvm/llvm-project#138579

An integration test is broken on the mlir-nvidia* bots.
2025-05-07 13:43:55 +02:00
Krzysztof Drewniak
c7c1283ab2
[mlir][MemRef] Remove integer address space builders (#138579)
The forms of the MemRef builder that took an integer argument instead of
an attribute have been deprecated for years now, and have almost no
upstream uses (the remaining ones are handled in this PR). Therefore,
remove them.
2025-05-06 11:22:15 -05:00
Kazu Hirata
921d162460
[mlir] Remove unused local variables (NFC) (#138642) 2025-05-06 07:55:50 -07:00
Krzysztof Drewniak
640103b91a
[mlir][MemRef][~NFC] Move getStridesAndOffset() onto layouts (#138011)
This commit refactors the getStridesAndOffet() method on MemRefType to
just call `MemRefLayoutAttrInterface::getStridesAndOffset(shape,
strides& offset&)`, allowing downstream users and future layouts (ex, a
potential contiguous layout) to implement it without needing to patch
BuiltinTypes or without needing them to conform their affine maps to the
canonical strided form.
2025-05-05 09:09:32 -07:00