Commit graph

2734 commits

Author SHA1 Message Date
Scott Manley
f8d6aaf8ca
[flang][NFC] move addPass* template utilities to header (#213288)
Move the addPass* template utilities to the header so external pipelines
can use them.
2026-07-31 13:30:31 -05:00
Valery Dmitriev
5e67107334
[flang] Do not convert load and store FIR ops to memref if volatile (#212884)
Memref dialect has no way to express volatility currently. Let such FIR
operations to stay as FIR to be handled by CodeGen in path to LLVM.
2026-07-31 10:10:28 -07:00
Eugene Epshteyn
d73beb2ee6
[flang] Delete the unused ragged-array runtime builders (#213160)
The ragged-array machinery served the legacy FORALL mask temporaries,
whose lowering was removed with the legacy expression lowering (#210639,
#210873) and the array-value-copy pass (#212643). The builders
(fir::runtime::genRaggedArrayAllocate/Deallocate) and the
getRaggedArrayHeaderType helper have no compiler callers left; only
their own unit test exercised them. Delete the builders, the helper, and
the unit test.

The flang-rt runtime entry points
(RaggedArrayAllocate/RaggedArrayDeallocate in
flang-rt/lib/runtime/ragged.cpp and their declarations in
flang/include/flang/Runtime/ragged.h) are ABI and remain.

Assisted-by: AI
2026-07-31 09:29:43 -04:00
Eugene Epshteyn
95ee221ea8
[flang] Delete the legacy array-value operations from FIR (#213159)
Nothing in flang has produced fir.array_load, fir.array_fetch,
fir.array_update, fir.array_modify, fir.array_access, fir.array_amend,
or fir.array_merge_store since the legacy (non-HLFIR) expression
lowering was deleted (#210385, #210621, #210639, #210873), and the
array-value-copy pass that legalized them is gone (#211816, #212643).
Delete the operations and the surface that existed only for them:

- FIROps.td: the "Array value operations" section including the
copy-in/copy-out design comment; FIROps.cpp: the ops verifiers, effects
and getExtents. fir.array_coor is unrelated and stays, as does the
validTypeParams helper shared with fir.pack_array.
- Tests: the ops roundtrip/verifier blocks in fir-ops.fir and
invalid.fir; scaffolding rewrites in inline-elemental.fir (store via
hlfir.designate; hlfir.apply-in-do_loop coverage preserved),
loop-versioning.fir @test4 (the versioned loops are untouched), and
simplifyintrinsics.fir (inert copy-back loops dropped; no CHECK lines
affected).
- Docs: FIRArrayOperations.md (+ the index.md toctree line); past-tense
updates in HighLevelFIR.md; a stale comment in MutableBox.h; a
release-note entry recording the removal for downstream projects.
FIRLangRef is generated from FIROps.td and follows automatically.

Assisted-by: AI
2026-07-31 08:47:13 -04:00
Kareem Ergawy
5eb4272b04
[flang][CodeGen] Replace fir.select* FIR-to-LLVM patterns with stubs that emit conversion errors (#212978)
`fir.select`, `fir.select_case`, `fir.select_rank`, and
`fir.select_type` are lowered to cf.* earlier in the pipeline
(`--fir-select-ops-conversion` and `--fir-polymorphic-op`). Their
FIR-to-LLVM conversion patterns are dead in a correct pipeline. Replace
them with a single templated stub
`SelectShouldHaveBeenConvertedStub<OP>` that emits `"'fir.<op>' op
should have already been converted"` and fails legalization, so running
`--fir-to-llvm-ir` standalone on stale IR reports a clear diagnostic
instead of "unable to legalize".

`Fir/convert-to-llvm.fir`'s six select* test blocks are removed (the
lowering no longer runs; CF-level coverage lives in
`Fir/SelectOpsConversion/`). `Fir/convert-to-llvm-invalid.fir` gains a
stub-error test per op. `Fir/Todo/select_case_with_character.fir` is
retargeted to check the equivalent diagnostic now emitted by
`--fir-select-ops-conversion`.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>

PR Stack:
* https://github.com/llvm/llvm-project/pull/212977
* ▶️ https://github.com/llvm/llvm-project/pull/212978

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-07-31 09:26:26 +02:00
yebinchon
21d9869c20
[flang] Add a pass to get OpenACC device ptr for CUDA kernel (#212299)
When a CUDA kernel is launched inside an OpenACC data region, it does
not properly get the device pointers and instead uses host data. This PR
adds a pass to get the device pointers set up by the OpenACC data
construct and pass them explicitly to the CUDA kernel.

Note: A possibly non-contiguous array argument is currently not supported. This pass will skip these cases.

---------

Co-authored-by: Yebin Chon <ychon@nvidia.com>
2026-07-30 14:06:28 -07:00
Kareem Ergawy
730b803ed0
[flang][Transforms] Add SelectOpsConversion pass (#212977)
Introduces `--fir-select-ops-conversion`, which lowers `fir.select`,
`fir.select_case`, and `fir.select_rank` to the control-flow dialect
(`cf.switch` / `cf.cond_br` / `cf.br`) while preserving the CFG shape.
`fir.select_case` becomes an if-then-else ladder of `arith.cmpi` +
`cf.cond_br`; Fortran `UNSIGNED` selectors use `ule`. Signed / unsigned
FIR integer values are normalized to signless via `fir.convert` first.

`fir.select_type` is not handled here — it is already lowered by
`--fir-polymorphic-op` (`PolymorphicOpConversion`).

The pass runs in the default FIR optimizer pipeline right after
`PolymorphicOpConversion`. Pipeline-check tests are updated to expect
`SelectOpsConversion` in the sequence; `Fir/select.fir` and
`Lower/volatile3.f90` are relaxed to accept the newly-canonicalized form
of the lowered output.

The main purpose of moving these conversion pattern earlier in the MLIR
pipeline and target `cf` instead of directly `llvm` is to be able to
later on use control-flow to structured-control-flow lifting:
https://github.com/llvm/llvm-project/blob/main/mlir/include/mlir/Conversion/Passes.td#L402.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>


PR Stack:
* ▶️ https://github.com/llvm/llvm-project/pull/212977
* https://github.com/llvm/llvm-project/pull/212978

---------

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-07-30 19:53:45 +02: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
Eugene Epshteyn
31d99ba9e2
[flang] Delete the array-value-copy pass (#212643)
Since the removal of the legacy expression lowering (#210385, #210621,
#210639, #210873) nothing in flang produces the array-value operations
this pass legalizes, and #211816 already removed it from the default
pipeline. Delete the pass and the pieces that existed solely for it:

- ArrayValueCopy.cpp, its Passes.td definition,
createArrayValueCopyPass, and the (duplicated) CMake source entries.
- Optimizer/Builder/Factory.h in its entirety: the pass was its only
includer, and its contents (attrFortranArrayOffsets,
getExtents/getOrigins on shape values, originateIndices) have no other
users.
- The getTypeParams(fir::ArrayLoadOp) overload (sole caller was the
pass) and the ArrayLoadOp forward declaration in BoxValue.h.
- The pass LIT tests (array-value-copy*.fir, array-copies-pointers.fir,
array-modify.fir); stack-arrays-hlfir.f90 drops the --array-value-copy
stage from its RUN pipeline.
- The pass-describing paragraphs in fstack-arrays.md and the stale
ArrayValueCopy TODO entry in ParameterizedDerivedTypes.md.

The array-value operations themselves (fir.array_load and friends; not
fir.array_coor) remain in the dialect and will be deleted in a
follow-up.

Assisted-by: AI
2026-07-30 09:38:00 -04:00
jeanPerier
ab7bbbbdc7
[flang][AllocationPlacement] prevent promotion of mock result to allocmem (#212825)
Under the new experimental pass that can move automatic arrays to the
heap, "mock" result storage may be promoted to allocmem before
AbstractResult removes them and replace them by a hidden result.

Add a fir.must_be_stack attribute to these mock alloca so they are never
promoted. So that passes dealing with array function results ABI can
expect to find an fir.alloca and remove it.
2026-07-30 11:34:01 +02:00
agozillon
c94c7cc893
[Flang][OpenMP] Remove present modifier application on descriptor (#211856)
This was a minor change upstreamed in the original PR:
https://github.com/llvm/llvm-project/pull/208133

However, it is a modification that needs a little more thought from a
specification perspective before it is rolled out, there's a number of
code bases that depend on the presence modifier being applied only to
the underlying data. However, this leads to inconsistencies when a user
makes use of any reference semantic modifiers when mapping as they
SHOULD be allowed to specify present applying to the descriptor. So, we
need to work out what the correct defualt behaviour is, and regardless
of the default support a user intentionally specifying presence
application on a descriptor via reference semantics.

For now, we will revert to previous state.
2026-07-30 05:18:00 +02:00
Valentin Clement (バレンタイン クレメン)
a9349342b2
[flang][cuda] Unify registration under -gpu=mem:unified (#212871)
Always use the cuf operation under -gpu=unified as registration might be
differed to the backend. Add a UnitAttr to distinguish device resident
variable that will not use cudaRegisterHostVar but cudaRegisterVar.
2026-07-29 23:05:58 +00:00
Matsu
c8c6c0ff74
[flang] Drop nuw on XArrayCoor for non-positive slice steps (#212639)
Example:
```fortran
z(:, 3:2:-1) = z(:, 1:2)
```

In this code, reverse-section indexing lowers `idx*step` / `diff+adj`
with `nuw`. A negative step can make the product negative, so `nuw` is
invalid and LLVM `-O2` can drop the stores.

Fix: keep `nsw|nuw` only for known positive steps; otherwise keep `nsw`
and drop `nuw` (negative, zero, or unknown).
2026-07-29 06:16:55 -07:00
jeanPerier
5989d40ab1
[flang] Wire allocation-placement into the optimizer pipeline (default off) - memory passes unification [3/5] (#210745)
Add a hidden -enable-allocation-placement flag that, when set, replaces
the stack-arrays and memory-allocation-opt passes in the default FIR
optimizer pipeline with the unified allocation-placement pass. The flag
is off by default, so the legacy passes remain the default path and
behavior is unchanged.

When enabled, the pass runs with its default byte-size thresholds; the
-fstack-arrays strategy is forwarded through the new stackArrays option.

Assisted-by: AI
2026-07-29 13:31:04 +02:00
jeanPerier
005c18eac0
[flang] Add policy-driven allocation-placement pass - memory passes unification [2/5] (#210742)
Introduce a new function-level pass, allocation-placement, that unifies
the stack/heap placement decisions currently split between the
stack-arrays and memory-allocation-opt passes. For each array allocation
it consults a policy to decide whether it should live on the stack
(fir.alloca) or the heap (fir.allocmem) and rewrites it accordingly,
reusing fir::replaceAllocas for stack-to-heap and the StackArrays
analysis/rewrite for heap-to-stack (so heap-to-stack only happens where
it is provably safe).

The default policy (AllocationPlacementPolicy.h) is threshold-driven:
- small constant-size arrays go on the stack within a per-function stack
budget, otherwise on the heap;
- big constant-size arrays: user variables stay on the stack,
temporaries go on the heap;
  - runtime-sized arrays go on the heap;
- an aggressive mode places all arrays on the stack (best effort). User
variables are distinguished from compiler temporaries via the presence
of a uniqued name. A hook lets downstream users override the thresholds
per allocation (e.g. for device routines or parallel regions).

The pass is not wired into any pipeline yet; it is reachable through
fir-opt and covered by isolated tests.

Assisted-by: AI
2026-07-29 11:01:47 +02:00
Valentin Clement (バレンタイン クレメン)
16f45b7f18
[flang][cuda] Add option to set priority to the CUDA Fortran constructor (#212561) 2026-07-28 11:28:36 -07:00
Eugene Epshteyn
034f0f1ad4
[flang] Stop running array-value-copy in the default pipeline (#211816)
Since the removal of the legacy expression lowering (#210385, #210621,
#210639, #210873), nothing in flang produces the array-value operations
(fir.array_load and friends) that the array-value-copy pass legalizes,
so the pass runs as a guaranteed no-op on every function. Remove it from
the default pipeline (addAVC and the disable-avc mlir option); the pass
itself and its fir-opt tests remain and still run via fir-opt
--array-value-copy.

The array-value operations themselves and the pass are planned for
removal in follow-up patches.

flang/test/Fir/arrexp.fir is deleted rather than updated: it feeds
legacy array-value ops through tco's full pipeline, which no longer
legalizes them (the ops have no codegen patterns), and the file
exercises no live feature beyond that legalization.

Assisted-by: AI
2026-07-28 10:59:35 -04:00
jeanPerier
9a5434468b
[flang][NFC] Extract StackArrays analysis and rewrite into a header - memory passes unification [1/5] (#210721)
Move InsertionPoint, StackArraysAnalysisWrapper, and AllocMemConversion
out of the anonymous namespace in StackArrays.cpp into a new
StackArrays.h header (in namespace fir), so the "which fir.allocmem can
be safely moved to the stack, and where" analysis and the heap-to-stack
rewrite pattern can be reused by other passes.

The dataflow internals (AllocationState, LatticePoint,
AllocationAnalysis), the command-line options, and all method
definitions remain in the .cpp. No functional change intended.

RFC:
https://discourse.llvm.org/t/rfc-flang-improving-temporary-and-local-array-allocations-unify-stackarray-memoryallocation/91353

Assisted-by: AI
2026-07-28 08:39:52 +02:00
Valentin Clement (バレンタイン クレメン)
30bff76d3a
[flang][cuda] Do not emit cuf.register_variable_static for device/constant under unified mode (#212344) 2026-07-27 20:59:07 +00:00
Razvan Lupusoru
b8bd63c69c
[flang][acc] Emit NYI messages for unsupported directives (#211894)
Add an OpenACC MLIR pass that emits not-yet-implemented messages for
unsupported directives immediately after HLFIR generation. This allows
OpenACC dialect operations to be emitted with -emit-hlfir while making
full compilation fail early with clear diagnostics, instead of later
when unhandled OpenACC operations reach LLVM dialect conversion.
2026-07-27 10:10:49 -07:00
Valentin Clement (バレンタイン クレメン)
7354df8e74
[flang][cuda] Keep cycle-broken device globals defined (#211897)
Breaking cyclic global initializers by removing an initializer produced
an
external declaration, which could leave references unresolved during
device
linking.

Replace selected cyclic initializers with zero initializers instead.
This
breaks the NVPTX dependency cycle while preserving device symbol
definitions.
2026-07-24 15:14:59 -07:00
Valentin Clement (バレンタイン クレメン)
9d7095fb78
[flang][cuda] Use cuf.register_variable_static instead of CUFRegisterExternalVariable (#211886)
This gives more flexibility to the backend to select a different
registration mechanism
2026-07-24 12:57:55 -07:00
Pranav Bhandarkar
e949b65442
[flang][OpenMP] Fix alias analysis for omp.private copy region block arguments to help inline hlfir.assign to improve time taken in LTO. (#209539)
## Summary

This PR fixes https://github.com/llvm/llvm-project/issues/200922 - a
compile-time regression affecting firstprivate clauses on simple arrays
in OpenMP target regions.

When `InlineHLFIRAssign` checks whether to inline `hlfir.assign`
operations in `omp.private` copy regions, the alias analysis
conservatively returns `MayAlias` for the copy region block arguments
(`%arg0` mold vs `%arg1` private). This prevents inlining and forces a
fallback to `fir.call @_FortranAAssign`, which:

- Pulls in 89 runtime functions via LTO
- Creates 550K+ abstract attributes in OpenMPOpt
- Causes severe compile-time degradation (60%+ increase in some cases)

**Example:**
```fortran
!$omp target firstprivate(array)
  ! ... use array ...
!$omp end target
```

The firstprivate copy generates an `omp.private` copy region where the
assignment from the original array to the private copy cannot be inlined
due to conservative aliasing assumptions.

## Root Cause and Solution

The FIR alias analysis did not recognize that `omp.private` copy region
block arguments are guaranteed by the OpenMP specification to reference
different memory locations:
- `%arg0` (mold) - the original variable
- `%arg1` (private) - freshly allocated private storage created in the
init region

Since the private copy is allocated fresh, these arguments **cannot
alias**.

So, this PR adds special-case handling in
`flang/lib/Optimizer/Analysis/AliasAnalysis.cpp` to recognize
`omp.private` copy region block arguments and correctly return
`NoAlias`. This allows `InlineHLFIRAssign` to inline the assignment into
an element-wise loop, avoiding the expensive runtime call entirely.

Assisted by: Claude Sonnet

---------

Co-authored-by: Claude Sonnet 4 <noreply@anthropic.com>
2026-07-24 13:56:30 -05:00
Matsu
044d3462c6
[flang] Set nsw on FIRToSCF loop induction increments (#211796)
Example:
```fortran
subroutine sum_loop(a, n)
  integer :: a(n), i
  do i = 1, n
    a(i) = i
  end do
end
```

In this code, the DO induction variable `i` is stepped each iteration.
`FIRToSCF` lowered that increment to a plain `arith.addi` with no
overflow flag — unlike the CFG-conversion path (`ControlFlowConverter`),
which marks it `overflow<nsw>` — so LLVM must assume the IV may wrap and
cannot form an affine recurrence, blocking analysis/vectorization of
loops lowered via `fir-to-scf`.

Fix: add a `set-nsw` pass option (default `true`, disabled under
`-fwrapv`) and mark the typed-IV, reconstructed final-value, and
`iterate_while` increments `nsw`, matching `ControlFlowConverter`;
`FirToSCF` lit tests updated accordingly.
2026-07-24 08:29:08 -07:00
Vijay Kandiah
df68991c06
[flang][cuda] Fix CUFPredefinedVarToGPU for a shared builtin address_of (#211628)
`CUFPredefinedVarToGPU` rewrites references to the predefined CUDA
builtins (`threadidx`/`blockidx`/`blockdim`/`griddim`) into GPU special-register
reads. For each predefined-var `fir.declare` it also erased the declare's
backing `fir.address_of`. That assumed every declare owns a
private `address_of`, which is only true before CSE. Once a single
`fir.address_of` of a builtin is shared by several `fir.declare`s — e.g.
after a `device` routine is inlined into a `global` kernel and CSE coalesces the
duplicated `address_of` ops — the pass queued that one op for deletion
once per declare and erased it while another declare still used it, thus aborting
compilation with `'fir.address_of' op operation destroyed but still has uses` error.

With this PR, the backing ops are collected into a de-duplicated set and
erased after all predefined declares are gone, and only when `use_empty()`.
This makes the deletion safe regardless of how many declares share an
`address_of`, and leaves it untouched if any other user remains.
2026-07-23 13:05:37 -05:00
Eugene Epshteyn
2c8d11e8d4
[flang][NFC] Delete the legacy expression lowering (ConvertExpr.cpp) and its support files (#210873)
The legacy (non-HLFIR) lowering was removed in cc4922b276 (#196205),
but ConvertExpr.cpp and its ComponentPath/IterationSpace support files
were left behind. Their last callers have since been migrated or removed
(#210385: OpenMP iterator subscripts via genExprValue; #210621: initial
values via ConvertConstant; #210639: unreachable FORALL/WHERE machinery
deleted from Bridge.cpp), so nothing outside these files references them
anymore.

- Delete ConvertExpr.{cpp,h}, ComponentPath.{cpp,h},
IterationSpace.{cpp,h}. (createArrayLoads/createArrayMergeStores are
declared in IterationSpace.h but were defined in ConvertExpr.cpp - they
die together; no external callers.)
- CMakeLists.txt: drop the three sources and the ConvertExpr.h /
IterationSpace.h PRECOMPILE_HEADERS entries.
- Remove stale includes (verified symbol-free): IO.cpp,
OpenMP/OpenMP.cpp, DirectivesCommon.h (ConvertExpr.h); Allocatable.cpp,
Support/Utils.cpp (IterationSpace.h).
- Support/Utils.{h,cpp}: remove the ExplicitSpaceArrayBases alias and
its getHashValue/isEqual overloads; the SomeExpr* and Component*
variants stay (live via ExprToValueMap and HLFIR lowering).
This also deletes six small Optimizer/Builder helpers whose last callers
were in ConvertExpr.cpp — fir:🏭:genLenOfCharacter,
getNonDeferredLenParams, getExtentFromTriplet (FIRBuilder),
getExtentAtDimension (BoxValue), fir:🏭:getRealloc
(LowLevelIntrinsics), and the genCharacterCopy template (Factory.h).
Their removal orphans nothing further; Factory.h and LowLevelIntrinsics
retain their live content.
- Docs: drop the ConvertExpr.cpp section from fstack-arrays.md and the
stale ConvertExpr.cpp TODO inventories from ParameterizedDerivedTypes.md
and ProcedurePointer.md.
No functional change: everything removed is unreachable. Downstream
forks using the deleted entry points will break at compile time; this is
intended (precedent: cc4922b276).

Assisted-by: AI
2026-07-22 23:15:19 -04:00
Valentin Clement (バレンタイン クレメン)
dc698fa68c
[flang][cuda] Break circular global init when copying them to the GPU module (#211100)
PTX does not support cycle in globals. 

```
error: Circular dependency found in global variable set
```

To avoid cycle in type descriptor, check if there is a cycle and break
it.

The algorithm uses Tarjan’s strongly connected components algorithm for
finding strongly connected components in a directed graph.
- Each fir.global is a graph node.
- Each fir.address_of in a global initializer is an edge to another
global.
- An SCC containing multiple globals—or a self-edge—represents a
circular initializer dependency.
2026-07-22 13:13:39 -07:00
Vijay Kandiah
c416cc1b3a
[flang][cuda] Fix cuf-alloc-delay for host-associated allocatables (#211103)
`cuf-alloc-delay` sinks a managed descriptor's `cuf.alloc` group
(`{cuf.alloc, fir.store, fir.declare}`) to just before its first use, to
defer the managed allocation. It special-cased the store of the descriptor
into a host-association tuple slot (`fir.store` to a `fir.llvm_ptr`): it did
not count that store (nor the call that consumes the tuple) as a use, and moved
the store along with the group. As a result, when a managed allocatable descriptor
is stored into a host-association tuple and passed to an internal procedure, the group
could be sunk **past** the internal-procedure call that reads the tuple, so the
callee observed an uninitialized descriptor. On more complex tuples, moving the
host-association store also broke SSA dominance, producing
`operand #1 does not dominate this use`.

With this PR, `findDelayTarget` now treats **every** use of the
descriptor as a real use, including the host-association store. The group is only ever sunk to
*before* the first use, and the host-association store is never moved (it reads
its own `fir.coordinate_of` slot). This keeps the descriptor initialized before
the tuple is consumed and is dominance-safe by construction.
2026-07-22 11:36:27 -05:00
Tom Eccles
9286c58841
[Flang] Return APInt from getIntIfConstant (#211233)
Preserve the full bit width of integer attributes when extracting
constants from FIR values. Return llvm::APInt directly and update
fixed-width consumers to use checked signed extraction.

This avoids truncating or asserting on constants wider than 64 bits
while retaining existing fallback behavior at int64_t boundaries.

This should be NFC everywhere we didn't have a latent overflow bug. I
didn't go so far as updating the interfaces of every function built on
top of getIntIfConstant: this is mostly to make an APInt version
available because it looks useful for another PR. Fixing the builder API
to use APInt would be a larger change - let me know if anyone wants to
see that.

Assisted-by: Codex
2026-07-22 17:35:07 +01:00
Caroline Newcombe
3486c5d48a
[flang] Region-based HLFIR operation for conditional expressions lowering (#194411)
Implements `hlfir.conditional`, a region-based HLFIR operation that
represents Fortran 2023 conditional expressions (10.1.2.3) with lazy
branch evaluation.
Issue #176999
Assisted-by: Claude Sonnet 4.5
2026-07-22 11:55:27 -04:00
Valentin Clement (バレンタイン クレメン)
009e841dbd
[flang][cuda] Add option for allocator registration function to CUFAddConstructor (#211098)
This allows to register different allocators when needed.
2026-07-21 20:41:14 +00:00
nvptm
5b6ebc25e0
[flang][cuda][openacc] Support CUDA calls to ACC routines (#210165)
Enable CUDA device procedures to call !$acc routine procedures.

- Treat ACC routines as device-callable during CUDA semantic checking.
- Apply implicit-device dummy argument handling to ACC routines called
from CUDA device code.
- Defer CUDA cloning of ACC routines until ACC lowering materializes and
moves the specialized routine into the GPU module.
- Add a CUF device-function transform regression test.
2026-07-21 12:47:25 -07:00
Soham Karandikar
9eac681359
[Flang] [OpenMP] Run MarkDeclareTarget pass again before HostOpFiltering (#210049)
Fixes #209123.

The power operation `math.ipowi` is converted to a function by
`ConvertMathToFuncs`. When used in a target region, this pass runs well
after `MarkDeclareTarget` which causes the newly created power function
to not have the `omp.declare_target` attribute, which in turn trips up
the `HostOpLowering` pass. Detailed investigation
[here](https://github.com/llvm/llvm-project/issues/209123#issuecomment-4991765854).

Right now, I've just added a couple of lines to run `MarkDeclareTarget`
again, before `HostOpFiltering`. Since I'm quite new to this, I'd like
some help on whether this is acceptable, or should the
`MarkDeclareTarget` pass be moved to after `ConvertMathToFuncs` and
before `HostOpFiltering`.
2026-07-21 15:02:59 +01:00
Valentin Clement (バレンタイン クレメン)
c26e99cf61
[flang][cuda] Avoid infinite loop while processing globals (#210805) 2026-07-20 19:33:39 -07:00
Slava Zakharin
7bbed7999d
[flang] Fold reads of fir.create_box components (#210388)
Fold fir.box_addr and constant-dimension fir.box_dims of a descriptor
built by fir.create_box back to the operands that built it, so the
create_box can die when nothing consumes it as a real descriptor.
fir.array_coor is intentionally not folded through create_box, since
that would drop its explicit byte strides.

Assisted-by: Cursor
2026-07-20 08:10:57 -07:00
Matsu
d9fff42ccd
[flang] Lower plain DO loops without a secondary-induction iter_arg (#207816)
Example:
```fortran
do i = lb, ub, step
  ...
end do
```

Flang lowers this with the DO variable as a redundant `iter_arg`, which
hides memory recurrences from later analyses. Simply removing it would
require converting the `index` IV to the source integer type each
iteration, potentially blocking vectorization.

Fix: allow `fir.do_loop` to use the DO variable’s integer type directly.
Trip-count and post-loop calculations remain in `index`. This removes
the redundant `iter_arg` without introducing per-iteration conversions.
`do concurrent` and unstructured loops are unaffected.
2026-07-20 11:10:54 +00:00
Matsu
5ec4a23630
[flang][cuda] Fix device-variable leaks and reset-safe cleanup (#209865)
Example:
```fortran
program main
  use cudafor
  integer, allocatable, device :: b(:)
  integer :: istat

  allocate(b(1024))
  b = 2
  istat = cudaDeviceReset()
end program
```

Managed descriptors and main-program allocatable data could leak. After
`cudaDeviceReset()`, compiler-generated scope-exit cleanup could also
access
stale descriptors or recreate a CUDA context.

Fix: free device data and descriptors in the correct order, and avoid
unnecessary
managed temporary descriptors. Each routine’s CUDA scope-exit cleanup is
grouped
under one `CUFDeviceIsActive()` check using
`cuDevicePrimaryCtxGetState`.
Routines without CUDA cleanup—and individual runtime frees—incur no
query.
2026-07-20 03:59:27 -07:00
Valentin Clement (バレンタイン クレメン)
372cd15f03
[openacc] Implicitly map external constant globals (#210408)
Hoist initializer-less constant globals out of OpenACC compute regions
so implicit data mapping handles them. This avoids unresolved device
symbols for PARAMETER arrays defined in separately compiled modules,
while retaining implicit declare for initialized constants. Add
regression coverage and a global initializer query to the OpenACC
interface.
2026-07-17 16:07:22 -07:00
Slava Zakharin
4070621c86
[flang][OpenACC] Discover type descriptors referenced by fir.create_box (#210393)
Register the IndirectGlobalAccess interface for fir.create_box so
acc-implicit-declare finds the derived-type type-descriptor global a
create_box of a record array needs on the device, as it already does
for fir.embox and fir.rebox.

Assisted-by: Cursor
2026-07-17 12:13:46 -07:00
Slava Zakharin
d63bd84293
[flang] Added fir.create_box operation. (#210220)
This patch adds `fir.create_box` operation that allows
creating `!fir.box<>` values with arbitrary byte strides.
It can be used to recreate boxes describing non-contiguous
arrays from descriptor components (base_addr/lbs/extents/strides)
across offload regions.

This is just initial definition and code generation code.
The folders and passes producing this operation will be added
later.
2026-07-17 09:58:41 -07:00
Valentin Clement (バレンタイン クレメン)
6f2bd9fd1a
[flang][cuda] Add option to flag descriptor I/O as error (#210170)
Descriptor I/O is too expensive in some compilation mode (nordc). Add
ability to emit an error if they are found in device code.
2026-07-17 06:28:36 +00:00
Valentin Clement (バレンタイン クレメン)
d49307497b
[flang][cuda] Register allocator when cuf.allocate or cuf.deallocate are present (#210147) 2026-07-16 20:39:07 +00:00
anoopkg6
378629b220
[flang] Derive target-specific data layout from triple in TargetRewrite (#209649)
When target-rewrite runs without an explicit llvm.data_layout attribute,
it falls back to hardcoded generic default in MLIR (kDefaultDataLayout)
which specifies f128 ABI alignment as 16 bytes. This is incorrect for
targets where f128 ABI alignment differs from its size, such as SystemZ
which requires 8 bytes per the ELF ABI.

The target triple is available in the target-rewrite pass. Fix by
deriving the data layout from the target triple using
triple.computeDataLayout() before falling back to the generic default,
ensuring target-specific alignments are correctly reflected in
dlti.dl_spec.

@uweigand @dominik-steenken

---------

Co-authored-by: anoop.kumar6@ibm.com <anoopk@b35lp63.lnxne.boe>
2026-07-15 20:08:17 +02:00
Valentin Clement (バレンタイン クレメン)
edea055ee8
[flang][cuda] Register allocator only when needed (#208355)
Register allocator only when needed to avoid bringing in symbol when not
strictly needed.
2026-07-15 09:25:48 -07:00
jeanPerier
d3f58ce0cc
[flang][openacc][NFC] remove useAccReductionCombine cl switch (#208756)
Follow-up of https://github.com/llvm/llvm-project/pull/208473 to remove
the switch altogether to simplify the compiler code.
2026-07-15 13:48:55 +02:00
Kaviya Rajendiran
ca71592c41
Reland "[Flang]Add support for inlining hlfir.assign operation where both LHS and RHS are slices of the same array #204532" (#208159)
Added support for inlining hlfir.assign when both LHS and RHS are slices
of the same array. When overlap between the slices cannot be determined,
the pass introduces a disjointness check:

- genIndexBasedDisjointnessCheck(..) is used when both sides are
sections of the same array.
- genAddressBasedDisjointnessCheck(..) used as a fallback for more
complex cases.

At runtime:

- If the slices are disjoint, a direct element-wise copy is performed
without allocating a temporary buffer.
- If overlap is possible, a temporary buffer is allocated, the RHS is
first copied into it and then the data is copied from the temporary
buffer to the LHS.

Fixes https://github.com/llvm/llvm-project/issues/203228
2026-07-15 16:48:11 +05:30
Vijay Kandiah
9035d06155
[flang][cuda] Size managed globals with descriptor components via LLVM Type (#209577)
When we do `-cuda -gpu=unified` (or `managed`) on a derived type with an
allocatable/pointer component, recent change
https://github.com/llvm/llvm-project/pull/209292 implicitly
attributed the component making lowering place the enclosing
derived-type global
in CUF managed memory. `CUFAddConstructor` then sizes that global via
`getTypeSizeAndAlignmentOrCrash`, which has no case for the descriptor
component
(`!fir.box<...>`) and aborts.

With this change, instead of aborting, we fall back to converting the
global to its LLVM type which
inlines the fixed-size descriptors, and query the data layout.
2026-07-14 14:02:28 -05:00
Caroline Newcombe
27dce19082
[flang][OpenMP] Resolve private array source from block-arg owner in alias analysis (#208227)
Part of #208086. `fir::AliasAnalysis::getSource` fails to recognize an
OpenMP private array as an `Allocate` source when its `hlfir.declare` is
nested inside an omp.loop_nest, and conservatively returns `MayAlias`.
This changes `getSource` to resolve the clause-carrying OpenMP op from
the private block argument's owner region, so the private is correctly
classified and does not spuriously alias other objects. Assisted-by: Copilot
2026-07-14 13:03:05 -04:00
Valentin Clement (バレンタイン クレメン)
83dc9c6c9a
[mlir][openacc] Remove OpenACCToLLVMIRTranslation (#209295)
OpenACCToLLVMIRTranslation was designed more than 5 years ago and does
not align with the current upstreaming effort. OpenACC will be converted
to LLVM IR dialect before the translation to LLVM IR so this translation
is obsolete. Remove it to avoid confusion.
2026-07-14 09:52:29 -07:00
Akash Banerjee
2a1200e08c
[Flang][OpenMP] Fix Fortran automap handling (#162501)
This fixes Fortran `declare target enter(automap:...)` handling for
allocatable
descriptors.

- Replace the previous `has_device_addr` target-region rewrite with
explicit
  target data operations around allocation/deallocation.
- On allocation, emit:
  - descriptor `map(always,to)` to keep the Fortran descriptor present
  - storage `map(storage)` for the allocated array data
- `map(attach)` to update the device descriptor base address to the
device data
- On deallocation, delete both the mapped storage and descriptor.
- Add a weak visible offload-entry alias for local/hidden `declare
target to/enter`
globals so libomptarget can associate the host descriptor with the real
device
  global without changing the original symbol linkage.

This fixes `offload/test/offloading/fortran/declare-target-automap.f90`
reported broken in #161265.

Co-authored-by: Codex <codex@openai.com>
2026-07-14 16:03:05 +01:00