Commit graph

8390 commits

Author SHA1 Message Date
Arun Thangamani
b32d4f0c45
[mlir][x86] Decouple Accumulator from ADD-Based Vector Contractions (over loops) (#204327)
This path transforms `vector.contract(A, B, Acc)` into
`vector.contract(A, B, 0) + Acc` to decouple the contraction computation
from the accumulator update for contractions over the loop.
2026-08-02 07:33:00 +05:30
Jianhui Li
007c684208
[mlir][xegpu] Add xegpu.lane_shuffle op (#210777)
Add a lane-level XeGPU operation that re-distributes a subgroup's
fragments across its lanes without changing the element type.

The op takes a 1D vector — the fragment held by one lane — and returns a
fragment of the same type. A pack/unpack mode selects the direction:
viewing the subgroup as an S x N element grid (S = subgroup size, N =
elements per lane), pack moves element j of lane i from logical position
j*S + i to i*N + j, so a lane's elements end up at consecutive
positions; unpack is the reverse.
  
This implements xegpu.convert_layout semantics at the lane level when
lane_layout is unchanged but lane_data differs.
  
assisted-by-claude

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-01 11:40:14 -07:00
Akimasa Watanuki
610a3105af
[MLIR][LLVM] Share LLVM metadata attribute translation (#203016)
Share LLVM dialect metadata materialization through `ModuleTranslation`
so named metadata and metadata-as-value lowering use one conversion
path. Resolve metadata symbol references to functions, globals, aliases,
and ifuncs, and diagnose malformed required metadata before lowering.

Rename `MDFuncAttr` to `MDGlobalValueAttr` to reflect its support for
symbol-backed global values.
2026-08-01 22:08:29 +09:00
Arun Thangamani
7b8d7c9d68
[mlir][x86] Adds extra pattern for AMX lowering (#213228)
This patch add extra pattern for `AMX` lowering, where the `M`, `N`, and
`K` loops are removed as part of `Canonicalization `
2026-07-31 20:25:06 +05:30
Bryth
c325d6fcb6
[mlir][complex] Fix canonicalize tests (#213259)
Remove trailing spaces and double line breaks, fix variable
re-definitions, make variables match regex consistent.
2026-07-31 16:18:21 +02:00
Zmicier Prybysh
3f9b96996c
[mlir][linalg] Support non-unit dilations in im2col decomposition (#208424)
The im2col patterns for conv_2d_nhwc_hwcf, conv_2d_nchw_fchw and
conv_2d_nhwc_fhwc avoided non-unit dilations, but the restriction
doesn't seem to be fundamental: dilation only affects the gather step,
which can fold it into its indexing map. Generalize the convolved index
expression from `oh * stride + fh` to `oh * stride + fh * dilation` and
drop the match failures.

Verified by comparing the results of a dilated convolution lowered
directly to loops against the im2col decomposition with mlir-runner.

Assisted-By: Claude Code (for generating tests).
2026-07-31 13:32:33 +01:00
Jeremy Johnson
814c0e672d
[mlir][tosa] Switch matmul_t output to bf16 from fp16 (#212970)
Note that this implements the TOSA specification change:
https://github.com/arm/tosa-specification/pull/67

---------

Signed-off-by: Jeremy Johnson <jeremy.johnson@arm.com>
2026-07-31 09:36:47 +01:00
Matsu
c836b82d08
[mlir][OpenACC] Atomicize contended shared array reduction updates (#212971)
Example:
```fortran
!$acc parallel loop gang reduction(+:a)
do i = 1, N
  !$acc loop worker reduction(+:a)
  do j = 1, M
    a(i) = a(i) + b(j,i)
  end do
end do
```

In this code, the worker accumulator is block-shared, so every worker
updates
the same element with a plain read-modify-write and all but one partial
is lost.

Fix: make in-place updates of a block-shared array accumulator atomic,
unless
the element index varies per thread, in which case each thread owns its
element
and the plain update is already race-free.

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 14:02:45 -07:00
Ivan R. Ivanov
056dae16f7
[mlir][gpu] Add stream-based async mode to gpu.launch (#213031)
Currently, only gpu.launch_func supports stream-based asynchronicity. This
patch adds the same mode to gpu.launch, and makes kernel outlining preserve
that when converting to gpu.launch_func.

This patch also documents the stream-based model in the operations description,
which was previously missing.

This patch changes the builders for the two launch operations:

To retain the current behavior for gpu.launch one needs to add a `nullptr` for
the new `Value asyncObject` argument after the `ValueRange asyncDependencies`,
and make sure to pass a valid type for the `Type asyncTokenType` parameter if
dependency-based async behavior is intended.

For gpu.launch_func, both stream-based and dependency-based async models now go
through the same builders, which take all three `Type asyncTokenType,
ValueRange asyncDependencies, Value asyncObject` arguments. To retain
stream-based behavior, pass `nullptr, {}` to the first two parameters, while to
retain dependency-based behavior, pass `nullptr` to the third parameter.

Assisted-by: Claude Code
2026-07-30 19:30:51 +02:00
Md Abdullah Shahneous Bari
9e43e04108
[mlir][arith] Gate min/max expansion in arith-expand behind include-min-max (#211884)
`arith-expand` expanded `arith.maximumf`/`minimumf`/`maxnumf`/`minnumf`
and the signed/unsigned integer max/min ops into `cmpf`/`cmpi` +
`select` sequences. These ops also have a direct arith-to-llvm lowering
to the `llvm.intr.maximum`/`minimum`/... intrinsics, which are a single
hardware instruction on many targets. Pipelines that run arith-to-llvm
after arith-expand (e.g. the GPU-to-XeVM pipeline) therefore paid a
large, avoidable overhead.

Add `include-min-max-f` (the float ops
maximumf/minimumf/maxnumf/minnumf) and `include-min-max-i` (the
signed/unsigned integer ops maxsi/maxui/minsi/minui) option (default `false`, changing the existing
behavior) that controls whether these min/max ops are expanded. The
min/max converters are factored into new
`populateExpandMinMaxFPatterns` and
`populateExpandMinMaxIPatterns`; the ceil/floor-div and scaling ext/trunc
expansions (which have no LLVM lowering) always run.

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-30 12:05:27 -05:00
Jianhui Li
ce25b1d727
[mlir][xegpu] Fix DPAS subgroup layout propagation for broadcast K dim (#211695)
This PR fixes an issue in getDpasSubgroupLayouts(): It failed to find
valid subgroup layouts for otherwise-legal DPAS ops. It treated the K
(contraction) dimension as distributed across subgroups — requiring
wgShape % sgLayout == 0 on every dim and gating on a
checkAlignedSgDataAB() equality — when K is actually broadcast: its full
extent stays in every subgroup. This rejected the only valid candidate,
causing layout propagation to bail out.
 
Update the two affected tests, which now propagate successfully instead
of failing.

assisted-by-claude

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-30 09:33:24 -07:00
Krzysztof Drewniak
188aa82fd8
[AMDGPU] Add ptr.s.buffer.load intrinsic, use it from Clang (#209243)
This commit adds a version of the existing s_buffer_load intrinsic that
more accurately models the memory semantics of the s_buffer_load
instruction, namely that it is, in fact, a memory load.

To preserve the existing behavior that the "nomem" s.buffer.load
intrinsic was using, Clang and MLIR add !invariant.load metadata when
constructing the intrinsic (matching documented requirements on
scalarazable buffer loads) and a late codegen pass adds the metadata
just to be safe.

Tests that were "about" s.buffer.load have been copied to create
versions that use the new intrinsic, as was done for the other
*.ptr.buffer.* operations.

Other tests have been upgraded to use the new intrinsic. This has mainly
resulted in minor instruction ordering changes in prologues, if any
change at all. However, CodeGen/AMDGPU/dagcombine-fma-fmad.ll has seen a
v_fma => v_mad pattern fail to match in one case, I don't know if this
is a real regression.

While I was here, the s_buffer_load => buffer_load fallback has been
updated to preserve cachepolity.

AI disclosure: Primarily AI-written code, but I have at least looked at
and tried to find the worst of the silliness.

---------

Co-authored-by: Codex <codex@openai.com>
2026-07-30 09:27:28 -07:00
Jianhui Li
665d200b16
[mlir][xegpu] Handle size-1 broadcast dim in insert_strided_slice layout setup (#211725)
This PR enhance `setupInsertStridedSliceResultLayout` to treat a size-1
source dim as a broadcast dim: keep its lane_data at 1 instead of
requiring divisibility.

Add regression tests for both the layout propagation setup and the
subgroup-to-lane distribution of such an op.

Assisted-by-claude

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-30 09:20:53 -07:00
Luke Hutton
f8c1d988e1
[mlir][tosa] Remove availability interfaces from profile conformance (#207809)
This commit removes the "QueryProfileInterface" and
"QueryExtensionInterface" as they are superfluous in most cases, with
TosaComplianceData.h.inc already providing much of the data we need.
Removing these also helps prevent mistakes as observed in:
https://github.com/llvm/llvm-project/pull/206687

This commit removes these interfaces and updates the profile conformance
to extract supported profile/extension information from
TosaComplianceData.h.inc instead.

One factor that isn't duplicated is operations that rely on extensions,
but do not declare any data type support. This is a small set of
operations, such as tosa.custom, tosa.cond_if, tosa.while_loop and
tosa.const_shape, and we can add them to the TosaComplianceData.h.inc
file as needed.
2026-07-30 11:47:06 +01:00
Chuanqi Xu
1a5fc1c6b6
[mlir] [linalg] Fold broadcast/transpose into linalg.generic (#212415)
Currently we are able to fold broadcast/transpose into
linalg.elementwise. This patch extends the ability to fold
broadcast/transpose into linalg.generic.

For example,

```
  %empty = tensor.empty() : tensor<8x16xf32>
  %broadcasted = linalg.broadcast ins(%A : tensor<8xf32>) outs(%empty : tensor<8x16xf32>) dimensions = [1]
  %result = linalg.generic {
    indexing_maps = [affine_map<(d0, d1) -> (d0, d1)>,
		     affine_map<(d0, d1) -> (d0, d1)>],
    iterator_types = ["parallel", "parallel"]
  } ins(%broadcasted : tensor<8x16xf32>) outs(%B : tensor<8x16xf32>) {
  ^bb0(%in: f32, %out: f32):
    %v = arith.addf %in, %in : f32
    linalg.yield %v : f32
  } -> tensor<8x16xf32>
```

we can fold the broadcast into:

```
  %result = linalg.generic {
     indexing_maps = [affine_map<(d0, d1) -> (d0)>,
                      affine_map<(d0, d1) -> (d0, d1)>],
    iterator_types = ["parallel", "parallel"]
  } ins(%A: tensor<8xf32>) outs(%B : tensor<8x16xf32>) {
  ^bb0(%in: f32, %out: f32):
    %v = arith.addf %in, %in : f32
    linalg.yield %v : f32
  } -> tensor<8x16xf32>
```

For simplicity, we only consider all parallel linalg.generic right now.

AI assisted.
2026-07-30 01:21:29 +00:00
Ian Tayler Lessa
03de9b148a
[mlir][tosa] Extend cancelling block-scaled cast optimisation to bf16 (#212517)
The CancellingBlockScaledCastsOptimization optimises away sequences
where a block-scaled tensor is cast to fp32 and then cast back to its
original block-scaled type.

This patch extends it to also cover cases where the intermediate type is
bf16, since the 7 bits of mantissa and 8 bits in the exponent are
sufficient to encode any `element * scale` product with valid
block-scaled type combinations.

---------

Signed-off-by: Ian Tayler Lessa <ian.taylerlessa@arm.com>
2026-07-29 14:31:19 +01:00
lonely eagle
b3115cd807
[mlir][affine] Add useExpensiveMath option to AffineLoopNormalize pass (#211989)
This PR integrates constant bound inference into the existing
`AffineLoopNormalize` pass under a new `useExpensiveMath` option. When
`useExpensiveMath` is enabled (disabled by default due to potential
compilation time overhead), the pass leverages
`ValueBoundsConstraintSet` (uss presburger) analysis to refine dynamic
`affine.for` loop bounds into compile-time constant bounds. RFC:
https://discourse.llvm.org/t/rfc-mlir-enable-dynamic-and-tighter-affine-unrolling-via-valueboundsconstraintset/91055/2

---------

Co-authored-by: Oleksandr "Alex" Zinenko <azinenko@amd.com>
2026-07-29 21:13:28 +08:00
vsimion26
61d6e494e9
QuantileType relax quantileType conditions and inheritance issue (#204793)
# Recategorize QuantileType as Storage Format, Not Quantization Scheme

## Summary

Reclassify `QuantileType` from inheriting `QuantizedType` to functioning
as a pure storage type.

## Motivation

### QuantileType is a Storage Format, Not a Quantization Scheme

After careful consideration, there was a conclusion reached that
**QuantileType should not be registered as a subtype of QuantizedType**.
The architectural distinction is critical:

- **QuantizedType** represents different quantization schemes (uniform,
per-axis, etc.), semantic operations that map values into a
lower-precision domain
- **QuantileType** is purely a **storage format** that specifies how to
interpret indices within a lookup table (LUT)

QuantileType was never meant to function as a quantization scheme on its
own. Instead, its purpose is to indicate **how to interpret indices
based on the given LUT**. It is an orthogonal concern to quantization
semantics; it describes data organization, not mathematical
transformation.

### Relaxed Type Conditions

The previous implementation restricted the LUT values to float types
only. However, float types are not the only types that can exist inside
a LUT, integer types are valid as well.

This PR removes the type restriction, allowing **both floating-point and
integer-based LUT interpretations** to coexist, better matching actual
use cases.

## Changes

- **Removed**: Incorrect inheritance of `QuantizedType` by
`QuantileType`
- **Relaxed**: Type constraints to accept both float and integer LUT
value types
2026-07-29 02:39:11 -07:00
Razvan Lupusoru
d8fb9ea73b
[mlir][acc] Add pass to emit remarks for openacc data mapping (#212623)
This pass emits MLIR remarks for all OpenACC data mapping actions.
Intended to be used when all the data actions are committed (typically
right before codegen to call runtime).
2026-07-28 21:41:46 +00:00
Moazin K.
93d45dce2f
[OpenACC] Do not clean up nohost routines in ACCRoutineLowering. (#212534)
The design of the ACC routine lowering supports multiple device side
specializations of an ACC routine function. Earlier in the pipeline, all
calls to the function are expected to refer the original host function
and not their device side specialized versions. Once there is enough
parallelism context, the calls can be changed to point to the
appropriate specialized routine.

The nohost handling in `ACCRoutineLowering` goes against this design.
This change removes the special handling of nohost routines and this
clean up should be done in later passes.

Assisted-by: Codex
2026-07-28 13:34:44 -07:00
Peng Sun
b626ec036e
[mlir][tosa] Add FP8 and MXFP support to RESIZE (#212276)
- Added FP8 and all six MXFP extension/type combinations
- Updated RESIZE availability and enforced NEAREST_NEIGHBOR for MXFP
- Added positive, negative, version, extension, mixed-type, and verifier
tests.

Signed-off-by: Peng Sun <peng.sun@arm.com>
2026-07-28 10:42:36 +01:00
Matsu
065179637e
[mlir][OpenACC] Lower single-block thread-only array reductions (#212369)
Example:
```fortran
!$acc parallel loop vector reduction(+:b)
do i = 1, n
  b(i) = i
end do
```

In this code the array reduction is thread(vector)-only with no
gang/block launch dim, so a within-block `all_reduce` is a complete
reduction. ACCCGToGPU still rejected it as NYI because the accumulate
had no block context.

Fix: keep the NYI only when the region actually launches block
dimensions; allow the existing per-element `all_reduce` path for
single-block thread-only array accumulates.
2026-07-27 21:21:02 -07:00
Stephen Long
289a2d901a
[mlir][LinalgBlockPackMatmul] Add support for scalable block factors (#211354)
Assisted by: Claude Sonnet 4.6

---------

Co-authored-by: Adam Siemieniuk <adam.siemieniuk@intel.com>
2026-07-27 14:44:04 -04:00
Chibuoyim (Wilson) Ogbonna
f92e977a8e
[MLIR][Linalg] Fix crash on duplicate dimensions in linalg.broadcast (#211203)
per
[#210738](https://github.com/llvm/llvm-project/pull/210738#discussion_r3622744153)

Currently, the following crashes on verification with a segfault:
```
func.func @broadcast_rank0_tensor(%arg0: tensor<i32>, %arg1: tensor<32x2xi32>) -> tensor<32x2xi32> {
  %0 = linalg.broadcast ins(%arg0 : tensor<i32>) outs(%arg1 : tensor<32x2xi32>) dimensions = [0, 0]
  return %0 : tensor<32x2xi32>
}
```

The verifier should reject cases like this where we have a duplicate
dimension. I've also added a couple of tests covering `linalg.broadcast`
on various input scenarios to confirm they are being handled properly.
2026-07-27 13:02:04 +01:00
Victor Perez
9349673459
[mlir][arith] Fold trivial shifts (0<<x, x>>x, -1>>x) (#212159)
Add value-preserving folds mirroring LLVM's InstructionSimplify for the
integer shift ops:

```
shli/shrui/shrsi(0, x) -> 0
shrui/shrsi(x, x) -> 0
shrsi(-1, x) -> -1
```

A shift amount greater than or equal to the bit width yields poison, so
refining these cases to a constant is valid. For `shr(x, x)` any
in-range amount `v` satisfies `v >> v == 0 (v < 2^v)`.

Folding an out-of-range shift amount (`c >= bit width`) to poison is
left as a TODO: it would make the arith dialect depend on the ub dialect
to materialize `ub.poison`.

LLVM performs the same simplifications: https://godbolt.org/z/7hsMz9E7Y

Verified with Alive2:

| Fold | shl | lshr | ashr |
| :--- | :---: | :---: | :---: |
| `0 << x`, `0 >> x -> 0` | [✓](https://alive2.llvm.org/ce/z/Sz2fT1) |
[✓](https://alive2.llvm.org/ce/z/mlq7k6) |
[✓](https://alive2.llvm.org/ce/z/jbeNH9) |
| `x >> x -> 0` | — | [✓](https://alive2.llvm.org/ce/z/JCPBCZ) |
[✓](https://alive2.llvm.org/ce/z/YLjo3M) |
 | `-1 >> x -> -1` | — | — | [✓](https://alive2.llvm.org/ce/z/sT6pNC) |

---

Code partially generated by Claude Code.

Signed-off-by: Víctor Pérez Carrasco <victor.pc.upm@gmail.com>
2026-07-26 21:41:00 -04:00
Victor Perez
677f13efef
[mlir][arith] Fix folds crashing on dynamic-shaped tensors (#212072)
`Builder::getZeroAttr` asserts when asked to build a constant of a
ranked tensor with a dynamic shape (`DenseElementsAttr` requires a
static shape). Three self-identity folds/patterns reached it without a
guard and aborted on dynamic-shaped operands:

```mlir
arith.xori %x, %x : tensor<?xi32>
arith.subui_extended %x, %x : tensor<?xi32>, tensor<?xi1>
arith.subi (arith.subi %a, %b), %a : tensor<?xi32>   (SubISubILHSRHSLHS)
```

Guard each with a static-shape check (as `arith.subi(x,x)` already does)
so they leave the op unfolded instead of crashing. The TableGen pattern
gets a new `IsScalarOrHasStaticShape` constraint.

Signed-off-by: Víctor Pérez Carrasco <victor.pc.upm@gmail.com>
2026-07-26 19:20:03 -04:00
Victor Perez
bdd8c64a2a
[mlir][arith] Fold trivial integer division and remainder (#212074)
Add value-preserving folds mirroring LLVM's InstructionSimplify for the
integer division and remainder ops:

```
divui/divsi/ceildivui/ceildivsi/floordivsi(0, x) -> 0
divui/divsi/ceildivui/ceildivsi/floordivsi(x, x) -> 1
remui/remsi(0, x) -> 0
remui/remsi(x, x) -> 0
```

The self and zero-dividend cases are valid refinements because division
or remainder by zero is undefined behaviour; no overflow flags are
required. The folds return a scalar or splat constant and bail out on
shaped types with a dynamic shape.

Folding `x / 0` and `x % 0` to poison is left as a TODO: it would make
the arith dialect depend on the ub dialect to materialize `ub.poison`.

LLVM performs the same simplifications: https://godbolt.org/z/dzTjYjs4e

Verified with Alive2:

| Fold | udiv | sdiv | urem | srem |
| :--- | :---: | :---: | :---: | :---: |
| `x / x -> 1`, `x % x -> 0` | [✓](https://alive2.llvm.org/ce/z/YjZCEA)
| [✓](https://alive2.llvm.org/ce/z/BSWQrm) |
[✓](https://alive2.llvm.org/ce/z/gx5sRH) |
[✓](https://alive2.llvm.org/ce/z/VUYkr4) |
| `0 / x -> 0`, `0 % x -> 0` | [✓](https://alive2.llvm.org/ce/z/keqeCZ)
| [✓](https://alive2.llvm.org/ce/z/jyf5wm) |
[✓](https://alive2.llvm.org/ce/z/fZa6ND) |
[✓](https://alive2.llvm.org/ce/z/fo6ss8) |

----

Code generated by Claude Code.

Signed-off-by: Víctor Pérez Carrasco <victor.pc.upm@gmail.com>
2026-07-26 16:25:34 +00:00
Byeongjee Kang
abd6e745e2
[MLIR][WasmSSA] Add global_set and select ops (#196613)
Adds two missing ops to the WasmSSA dialect.

- `wasmssa.global_set`
- `wasmssa.select`

---------

Co-authored-by: Ferdinand Lemaire <flscminecraft@gmail.com>
2026-07-26 01:35:53 +00:00
Victor Perez
7af5c42beb
[mlir][tosa] Fix mul/intdiv folds crashing on dynamic-shaped results (#212073)
`tosa.mul` and `tosa.intdiv` fold constant splat operands by building a
`DenseElementsAttr` of the result type, which asserts when that type has
a dynamic shape. When the operands are constants but the result type is
dynamic, folding aborted. Guard `mulBinaryFolder` and the `IntDivOp`
splat path on a static result shape, matching the other fold paths in
these ops.

Signed-off-by: Víctor Pérez Carrasco <victor.pc.upm@gmail.com>
2026-07-25 19:59:07 -04:00
Jianhui Li
cf95452508
[mlir][xegpu] Make convert_layout input_layout optional (#210833)
Make the `input_layout` attribute of `xegpu.convert_layout` optional.
When it is not set, the effective input layout defaults to
`target_layout`, i.e. the source is assumed to already be in the target
distribution.

assisted-by-Claude

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 20:08:53 -07:00
Chuanqi Xu
5295852db2
[mlir] [vector] Allow element/broadcast re-order for FMA if the source is a vector (#211208)
The diagnostic says the transform is not performed as the source may be
a scalar. But we can make it if we can check the source is not a scalar.

AI assisted.
2026-07-25 10:39:45 +08:00
Jianhui Li
8a6a039eb3
[mlir][xegpu] Allow create_mem_desc from ND memref (#211836)
Relax the create_mem_desc source operand constraint to accept a
statically shaped shared-memory memref of any rank, replacing the
1D/2D-only StaticShared{1,2}DMemRefOf classes with a rank-agnostic
StaticSharedMemRefOf.

Add a verifier requiring the source memref to be contiguous row-major,
update the op documentation, and add valid/invalid lit tests.

assisted-by-claude

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 12:01:20 -07:00
Caroline Newcombe
a2d74bfe38
[flang][OpenMP] Implement the error directive (#206175)
## [flang][OpenMP] Implement the `error` directive

### Summary

Implements the OpenMP `error` directive (OpenMP 5.1, 2.5.4) in Flang.
The directive prints a message and, with `severity(fatal)`, stops.
Handling depends on the `at` clause:

- **`at(compilation)`** (the default): handled in semantics. Emits a
compile-time warning or error and produces no IR.
- **`at(execution)`**: lowered to a new `omp.error` op, which becomes a
call to `__kmpc_error`.

Before this patch the directive was unimplemented and hit a `not yet
implemented: OmpErrorDirective` error during lowering.

Fixes #204240.

### Details

Changes go through the compiler pipeline.

**Flang semantics**
- `Enter(OmpErrorDirective)` emits the compile-time diagnostic for the
`at(compilation)` form, using the directive's severity and the `MESSAGE`
text when present.
- `Enter(OmpClause::Message)` checks that the `MESSAGE` expression is a
scalar, default-kind `CHARACTER`, which is required to pass it to the
runtime as a `const char*`.

**Flang lowering**
- `genErrorDirective` lowers the `at(execution)` form only.
- A constant message is stored in the `message` attribute. A
non-constant message is copied to a null-terminated buffer
(`genNullTerminatedString`) and passed as the `message_expr` operand,
because `__kmpc_error` expects a NUL-terminated string.

**New `omp.error` op (MLIR OpenMP dialect)**
- Adds a `ClauseSeverity` enum (`warning = 1`, `fatal = 2`, matching the
`__kmpc_error` argument) and `ClauseSeverityAttr`.
- `omp.error` takes a required `severity` attribute and an optional
message, given either as:
  - `message` — a constant string attribute, or
  - `message_expr` — a pointer to a null-terminated string.
- A verifier rejects providing both `message` and `message_expr`.

**MLIR → LLVM IR translation**
- Translates `omp.error` to `__kmpc_error(ident_t *, i32 severity, ptr
message)`.

**OMPIRBuilder**
- Adds `OpenMPIRBuilder::createError(...)`, which builds the call, maps
`fatal`→`2` and `warning`→`1`, and passes a null pointer when there is
no message.

### Tests

- **Parser** (`error-unparse.f90`): unparse and parse-tree output.
`at(compilation) severity(fatal)` cases that would stop compilation were
moved to `at(execution)`.
- **Semantics** (`Semantics/OpenMP/error.f90`): compilation
warning/error/default-severity cases, plus the new `MESSAGE` type, rank,
and kind errors.
- **Lowering** (`Lower/OpenMP/error.f90`): constant message, no message,
empty message, runtime `message_expr`, and `at(compilation)` cases that
must not produce `omp.error`. The old `Lower/OpenMP/Todo/error.f90` test
is removed.
- **MLIR** (`ops.mlir`, `invalid.mlir`): round-trip of each `omp.error`
form and the both-messages verifier error.
- **LLVM IR** (`openmp-llvm.mlir`): `__kmpc_error` calls for warning and
fatal, constant and runtime messages, and the null-message cases.

Assisted-by: Github Copilot
2026-07-24 10:43:05 -04:00
Hocky Yudhiono
fdbbcba77d
[mlir][affine] Add affine.for verifier and move arguments check earlier (#206685)
Fixes #206628 crash by adding an earlier body argument verifier for
`affine.for`. This crash is caused because `LoopLikeOpInterface`
verifier would call `getRegionIterArgs()` and assumed induction var of
`affine.for` exists.
2026-07-24 15:22:37 +02:00
Vitaly Buka
050c2ef111
Reland "[mlir][tosa] Combine unranked/ranked tensor types into single type" (#211708)
Reverts llvm/llvm-project#211701
Relands llvm/llvm-project#209737

The buildbot failure was misattributed to this change.
Real cause is https://github.com/llvm/llvm-project/pull/207274
2026-07-24 02:23:17 +00:00
Vitaly Buka
257e81f2e9
Revert "[mlir][tosa] Combine unranked/ranked tensor types into single type" (#211701)
Reverts llvm/llvm-project#209737

Breaks bots, see
https://github.com/llvm/llvm-project/pull/209737#issuecomment-5064857765
2026-07-24 00:36:46 +00:00
Bhavesh M
68d7f7b957
[mlir][EmitC] Add class-name-format option to wrap-emitc-func-in-class pass (#211147)
Added the `class-name-format` option that takes a format string used to
generate the wrapper class name.

This provides greater control over the generated `ClassOp` name. When
multiple identically structured IR files need to be programmatically
lowered with this pass and linked, there will be naming conflicts which
this patch provides a method of resolution for.
2026-07-23 15:32:43 -07:00
Scott Manley
c231e00b29
[OpenACC] set CollapseCountAttr for scf.parallel (#211676)
During compute lowering, also set the collapse count attribute when
creating scf.parallel ops from acc.loop ops. While this collapse count
is implied by the number of IVs, later canonicalizations may use this
information to decide whether or not to collapse the loop nest further
2026-07-23 17:24:17 -05:00
Matsu
f4b5fb1569
[mlir][OpenACC] Support partial ThreadX reduction launches (#211665)
Example:
```fortran
!$acc parallel loop collapse(2) num_gangs(10) reduction(+:a)
do i = 1, n
  do j = 1, n
    do k = 1, m
      a(k) = a(k) + x(k,i) * y(k,j)
    end do
  end do
end do
```

In this code, ACCCG pads ThreadX to the subgroup size because
`gpu.all_reduce` uses subgroup shuffles. This unnecessarily increases
private reduction storage when only one Y/Z row is active.

Fix: preserve partial ThreadX launches for a single row, while retaining
alignment when Y/Z rows could share a subgroup.
2026-07-23 14:54:50 -07:00
Vijay Kandiah
b1ff288ecd
[mlir][OpenACC] Emit multi-IV tile and element loops from ACCLoopTiling (#211651)
`ACCLoopTiling` used to lower an N-dimensional `tile()` clause by
*uncollapsing* the fused loop into a deep nest of single-IV `acc.loop`s
(`tile_1 → … → tile_N → elem_1 → … → elem_N`). This discards the natural
grouping of the tile clause: the 2N single-IV loops no longer express
"these are the tile iterations" and "these are the in-tile iterations"
as collapsible units, and gang/vector end up spread across a deep nest
where only the outermost loop of each group carries the attribute. This
could potentially lead to poor parallelism assignment.

With this MR:
`tileACCLoops` now rewrites the single fused `acc.loop` in-place into
exactly two multi-IV loops, each carrying all the tiled induction
variables:
- a **tile-group** loop whose steps are the original steps scaled by the
tile sizes, and
- a nested **element-group** loop that walks the iterations within one
tile, with upper bounds clamped to `min(origUB, tileStart +
tileExtent)`.

Keeping each group as a single multi-IV `acc.loop` preserves the
tile/element structure as two collapsible units instead of a 2N-deep
single-IV nest, which is a simpler canonical form. The
gang/worker/vector distribution across the two groups is unchanged from
before.

This change also diagnoses `tile` + `collapse` on the same loop because
these clauses give conflicting loop-association counts. The pass now
emits a NYI diagnostic instead of silently dropping the `collapse`
clause. Added a new invalid-input test to verify this.

With the pass no longer uncollapsing, `uncollapseLoops` and the
vector-of-loops `tileACCLoops(SmallVector<LoopOp>&, …)` overload (and
the now-orphaned `createInnerLoop` helper) are deleted, along with their
unit tests. New unit tests are added to cover the surviving fused-loop
overload.
2026-07-23 15:22:46 -05:00
nvptm
f7f9cc95db
[acc] Refine launch-dim handling for sequential block-redundant ancestors (#211153)
Sequential `gpu_block_redundant` ancestors need selective launch-dim
handling in `getAncestorParDims`: including them always widens
gang-private to per-thread; omitting them always can predicate
block-redundant bodies on `blockIdx` after partition.

Include launch dims when the block-redundant loop is worksharing or is
the innermost parallel parent; skip them for an outer sequential
block-redundant wrapper around nested worksharing.
2026-07-23 11:33:06 -07:00
Andrzej Warzyński
8b690a0854
[mlir][vector] Make CompressstoreOp + ExpandloadOp support scalable vectors (#210288)
Extends `vector.compressstore` + `vector.expandload` to support scalable
vectors and updates relevant tests.

An e2e test for `vector.compressstore` is added. For
`vector.expandload`, we need to wait for QEMU support:
https://github.com/llvm/llvm-project/issues/210942.
2026-07-23 15:40:26 +01:00
Federico Bruzzone
dcbf87542b
[mlir][sparse] Avoid vectorizing non-contiguous COO coordinate loads (#211004)
`SparseVectorization` assumes direct loop accesses (`a[lo:hi]`) are
contiguous and vectorizes them with `vector.maskedload/maskedstore`.
This is false for `sparse_tensor.coordinates` of a level inside a
trailing AoS COO region, whose buffer is interleaved with other levels:
a silent miscompile.

The true stride is already known from the tensor's encoding, even though
the memref type is still dynamic at this point. Use it to fall back to a
scalar loop when the stride is provably non-unit.

---------

Signed-off-by: Federico Bruzzone <federico.bruzzone.i@gmail.com>
2026-07-23 15:33:10 +01:00
Andrzej Warzyński
3cbb24bd54
[mlir][vector] Update CastAway{Extract|Insert}StridedSliceLeadingOneDim (#210902)
Update both:
  * CastAwayExtractStridedSliceLeadingOneDim
  * CastAwayInsertStridedSliceLeadingOneDim

to use vector.shape_cast, rather than vector.extract and
vector.broadcast, as the canonical form for stripping unit dimensions.

This change was originally implemented by @krzysz00 in #196206, but was
subsequently reverted in #199546. This PR intentionally restores only a
subset of #196206, making it easier to identify and triage any potential
regressions.

Co-authored-by: Krzysztof Drewniak <Krzysztof.Drewniak@amd.com>
2026-07-23 15:10:27 +01:00
Luke Hutton
aab7e0b08d
[mlir][tosa] Combine unranked/ranked tensor types into single type (#209737)
This commit refactors the defined TOSA types to combine unranked and
ranked tensor types into a single type `TosaTensorOf`. This helps
simplify the type definitions and allows all tensor types to support
both unranked and ranked tensors.
2026-07-23 14:41:27 +01:00
Matsu
d1c5983225
[mlir][OpenACC] Support dynamic multi-rank array reductions (#211336)
Example:
```fortran
integer :: r(:,:)
!$acc parallel loop reduction(+:r)
```

In this code, the reduction accumulator has dynamic dimensions and rank
greater than one.

Fix: use runtime dimension sizes to delinearize flattened
array-reduction indices.
2026-07-22 15:36:44 -07:00
Matsu
37879dc304
[mlir][OpenACC] Preserve worker rows when combining reductions (#210804)
Example:
```fortran
!$acc parallel loop gang worker reduction(+:sum)
do j = 1, n
  !$acc loop vector reduction(+:sum)
  do i = 1, n
    sum = sum + a(i, j)
  end do
end do
```

In this code, each worker has a private partial result, but combine
predication previously allowed only ThreadY row zero to contribute.

Fix: keep ThreadY active only for proven atomic worker combines, while
preserving legacy predication or reporting NYI for unsafe combinations.
2026-07-22 15:04:09 -07:00
Alexey Bataev
be34b478bf
[mlir][math] Fold FPowIOp with square-and-multiply to match powi expansion (#210982)
Fold math.fpowi using the base's own floating-point semantics via
iterative
square-and-multiply, matching the multiply sequence ExpandPowI builds in
SelectionDAGBuilder. The prior pow/powf-based fold computed in
float/double
and rounded differently from the runtime expansion, disagreeing with
x**n by ~1 ULP.
2026-07-22 15:35:44 -04:00
Jianjian Guan
8ae7803bed
[mlir][emitc] Add compound assignment ops (#210233) 2026-07-22 11:52:41 -07:00
Matsu
9659d3a8ae
[mlir][OpenACC] Forward dynamic boxed reduction extents (#211318)
Example:
```fortran
subroutine reduce(a, x, n)
  integer :: n, i
  real :: a(:), x(:)

  !$acc parallel loop reduction(+:a)
  do i = 1, n
    a(:) = a(:) + x(i)
  end do
end subroutine
```

`ACCCGToGPU` represents each gang/thread-private array as a dynamically
offset `memref.subview`. Converting this subview directly to a FIR
pointer-like type loses the memref offset, causing different private
copies to alias the same storage.

Fix: extract the selected subview’s element offset, convert it to bytes,
and create a zero-offset view at that address before converting to the
FIR pointer-like type. This preserves the selected gang/thread-private
slice.

Before:
```mlir
%subview = memref.subview %view[%block_id, 0] [1, %extent] [1, 1]
    : memref<?x?xf64> to memref<?xf64, strided<[1], offset: ?>>

%result = fir.convert %subview
    : (memref<?xf64, strided<[1], offset: ?>>) ->
      !fir.heap<!fir.array<?xf64>>
```

After:
```mlir
%subview = memref.subview %view[%block_id, 0] [1, %extent] [1, 1]
    : memref<?x?xf64> to memref<?xf64, strided<[1], offset: ?>>

%base, %offset, %sizes, %strides =
    memref.extract_strided_metadata %subview
    : memref<?xf64, strided<[1], offset: ?>> ->
      memref<f64>, index, index, index

%c8 = arith.constant 8 : index
%byte_offset = arith.muli %offset, %c8 : index

%private_view = memref.view %buffer[%byte_offset][%extent]
    : memref<?xi8> to memref<?xf64>

%result = fir.convert %private_view
    : (memref<?xf64>) -> !fir.heap<!fir.array<?xf64>>
```
2026-07-22 10:45:21 -07:00