Skip to content

merge main into amd-staging - #3694

Merged
ronlieb merged 75 commits into
amd-stagingfrom
amd/merge/upstream_merge_20260729164548
Jul 30, 2026
Merged

merge main into amd-staging#3694
ronlieb merged 75 commits into
amd-stagingfrom
amd/merge/upstream_merge_20260729164548

Conversation

@ronlieb

@ronlieb ronlieb commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

No description provided.

aobolensk and others added 30 commits July 29, 2026 15:07
This patch introduces the instrumentation passes and corresponding tests
for CopyProf, a profiling tool designed to identify unnecessary object
copies in C++ applications.
RFC at

https://discourse.llvm.org/t/rfc-copysanitizer-csan-detecting-unneccessary-object-copies-at-runtime/91038.

Three passes are added:
- CopyProfPass inserts enter/exit callback around special member
functions.
- CopyPRofStoresPass instruments store instructions to track memory
modifications.
- ModuleCopyProfPass inserts a module constructor to initialize the
CopyProf runtime at program startup (will be added later).
llvm#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>
)

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).
…llvm#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>
…Class. (llvm#208585)

fixes llvm#208437 

From LangRef for intrinsic convert_from_arbitrary_fp ,
"Normal finite values are converted exactly. NaN values follow LLVM’s
standard NaN rules; the NaN representation is preserved... and the NaN
payload may be truncated or extended..."
-> if src has Nan -> preserve nan

"If a value exceeds the representable range of the target type (for
example, converting Float8E8M0FNU with large exponents to half), the
result is converted to infinity with the appropriate sign."
Fix compile error with clang -Werror -Wunused-template
(cherry picked from commit 2b0bff7444a8df460daab2e5af18bce45ca00657)
While benchmarking with warnings enabled, I found that
`AnalysisBasedWarnings::getPolicyInEffectAt` runs at the end of every
function body, performing six location-sensitive `isIgnored()` queries.
This overhead comes from llvm#136323 ([compile-time
impact](https://llvm-compile-time-tracker.com/compare.php?from=2a9f77f6bd48d757b2d45aadcb6cf76ef4b4ef32&to=71ce9e26aec00e4af27a69ccfab8ca1773ed7018&stat=instructions:u)).

Since these six diagnostics only depend on the diagnostic state at the
query location and whether it is in a system header or macro, we can
cache the computed policy rather than recomputing it for every function.

The cache flushes when a `#pragma clang diagnostic` changes severities,
and it bypasses active diagnostic suppression mappings.

Compile-time results for this pr:

https://llvm-compile-time-tracker.com/compare.php?from=49de424f45389cb757c3cc8c50daf38d024e2314&to=a61503b54e9568254885777cf89f5ca1586ec99f&stat=instructions%3Au
… in case of -ffp-model=strict (llvm#212565)

1. reland the patch llvm#204170
2. and fix the regression caused by above patch.
GPR64arg was added in fcbec02 to describe X0-X7 for the reserved
argument-register check. It is an ABI register set rather than an
allocation constraint and should not be used for register allocation.
Given it has a single use that only cares about the number of registers,
a register class isn't necessary.

This exposes that GlobalISel recomputes the minimal register class when
a matching inline asm input is tied to a fixed physical-register output.
For X2 that class was GPR64arg, getRegistersForValue already asks the
target which class implements the output constraint. Retain that class
and reuse it for the matching input.

Assisted-by: codex
When building a `COPY` to legalise a generic operand whose register
class does not match what is expected, the subregister is not retained
in the copy, and is not dropped from the newly created virtual
destination register.
Avoids the assert immediately below.

Fixes llvm#45694

rdar://182744700
`SortIncludes` currently orders includes lexicographically with the
option to ignore case or extension. This adds another option, `Natural`,
that compares embedded runs of digits as numbers rather than sequences
of characters, matching the "natural sort" behaviour found in most file
managers and tools like `sort` when called with the `-V` option.

**Disclaimer**

AI assistance was used in initial exploration and review but the code is
"hand generated".
)

Consistently call the two argument overload
`MemorySSAWalker::getClobberingMemoryAccess(MemoryAccess,
MemoryLocation)` to get a clobbering def (according to the AliasAnalysis
used by MSSA) before applying the special cases in `isReallyAClobber`.

This has the effect of marking more loads as `amdgpu-noclobber` and
selecting SMEM load instructions for them.

Fixes: ROCM-28492
…ucts. (llvm#208533)

This patch fixes loop variable finalization for OpenMP 6.0
loop-transformations constructs: `tile`, `stripe`, `reverse`,
`interchange` and `fuse` to comply with spec requirement page 371, lines
19-21. The spec requires that "After the execution of the
loop-transforming construct, the loop-iteration variables of any of its
transformation-affected loops have the values that they would have
without the loop-transforming directive".
…d on std::mismatch() (llvm#210604)

This PR implements a parallel `std::adjacent_find()` based on parallel
`std::mismatch`. The implementation reshapes the input range as two ranges
offset by 1 element and asks `std::mismatch` to find the first equal pair.

Part of llvm#99938.
…lvm#204859)

In duplicateCondBranchOnPHIIntoPred, updateSSA iteratively updates the
uses of
the instructions of BB (the duplicated block) according to ValueMapping.
For
PHIs, however, the mapping is inconsistent: the keys refer to the values
before
the parallel assignment of the PHIs, while the mapped-to values refer to
the
values after it. E.g.

  BB:
    %arr  = phi [ %ov.0, %PredBB ], ...
    %ov.0 = phi [ %ov.sel, %PredBB ], ...
  --->
    %arr  => %ov.0
    %ov.0 => %ov.sel

So an iterative replacement miscompiles: a use of the duplicated %arr is
replaced by %ov.sel, while the correct replacement is %ov.0.

Fix this by splitting PredBB -> BB (SplitEdge) into a PredEdgeBB,
cloning the
PHIs into PredEdgeBB and mapping BB's PHIs to the clones:

  BB:
    %arr  = phi [ %ov.0, %PredEdgeBB ], ...
    %ov.0 = phi [ %ov.sel, %PredEdgeBB ], ...
  PredEdgeBB:
    %arr.dup  = phi [ %ov.0, %PredBB ]
    %ov.0.dup = phi [ %ov.sel, %PredBB ]
  --->
    %arr  => %arr.dup
    %ov.0 => %ov.0.dup

Since a distinct set of PHIs is used as the mapped-to values, the
iterative
replacement is correct.

Fixes llvm#197725.
Fixes llvm#203868.

Assisted-by: Opus-4.8 (Claude Code)
…m#212745)

On Windows `lldb --repl` can hang forever instead of exiting at EOF.

`IOHandlerEditline::GetLine` checks `GetLastError() ==
ERROR_OPERATION_ABORTED` and does a `continue` before checking `feof`.
However `fgets` is a CRT function and does not set the Win32 last error
value, so the `GetLastError` read is not the expected error. When it
happens to be `ERROR_OPERATION_ABORTED` (995) the loop never reaches the
EOF check.

This reorders the checks so EOF wins unconditionally, and adds
`clearerr` before the ctrl-c retry (a real interrupt leaves the error
flag set, which would fail the next `fgets`). ctrl-c handling is
otherwise unchanged.

rdar://183335061
…lvm#211824)

When vscale is known > 1, SVE will be used to perform most reductions.
This should be reflected in the cost model.
This cleanup patch pushes the auto-detection of the `macosx` SDK from
Makefile.rules up into `dotest.py` and unifies it with the existing SDK
handling for other Apple platforms.

Assisted-by: claude
When the loop index variable is smaller than the GEP offset size, and is
thus sign or zero extended before being used, then the IR that is
expanded from the SCEV expressions for the load and store locations will
be in a form that means GetPointerBaseWithConstantOffset can't deduce
the base and offset, meaning we can't generate memmove.

Solve this by deciding memmove validity based on the SCEV expressions
instead of the IR that is expanded from them. This means we also need to
insert a check to handle a null base pointer, as that was previously
handled implicitly due to how SCEVExpander expands expressions involving
null pointers.
…erand (llvm#211102)

With True16 instructions, the high-half packing idiom from llvm#206058 tries
to `OR` a 16-bit VGPR operand into the high half of the other operand,
but this causes a crash if the other operand is uniform, as this
generates an invalid `$sgpr = COPY $sgpr_hi16`.
The iterator passed-in may point to the end of the block which causes an
assertion failure when attempting to inspect the MI it points to. Guard
against this.
The following two expressions used to return the wrong truth table for
v_bitop3:

; ((b & T) | T) & ~T, where T = a & c

; U ^ (~U | T), where T = c ^ b and U = (T | a) & T

The fix was implemented in:
llvm#198556

Assisted-by: Cursor (Claude)
…llvm#212720)

Running `check-llvm` on Windows fails while compiling LLVMFrontendTests
with the following error:

  error: reference to 'detail' is ambiguous

Clang enables delayed template parsing by default when targeting the
MSVC ABI on Windows. When ConstructDecompositionT is instantiated after
a using-directive for `llvm::omp`, both `::detail` and
`llvm::omp::detail` are
visible, making `detail::find_unique` ambiguous.

Explicitly qualify find_unique with the global namespace. This fixes
check-llvm on Windows and other environments using
-fdelayed-template-parsing, without changing behavior.
akuhlens and others added 21 commits July 29, 2026 11:42
…1904)

Fortran 2023 7.6.1 errata f23/013 changes R762 so an interoperable
enumerator may be a named-constant initialized by a
boz-literal-constant, and specifies the value as
INT(boz-literal-constant, C_INT).

Handle that named-constant restriction directly in enum resolution while
preserving the usual scalar integer expression checks for non-enumerator
contexts. This mirrors the general named-constant initializer path,
which already converts BOZ values through the declared type before
folding.
Breaks unusual build configs where clang-tidy static analyzer is enabled
while clang static analyzer is disabled.

Reverts llvm#212024
…m#207292)

Summary: preprocessDWODebugInfo() eagerly force-extracted every .dwo
compile unit's DIE tree (getNonSkeletonUnitDIE(false)) very early in
BOLT pipeline, way before DWARFRewriter kicked in. Those vectors then
sit in memory throughout the entire rewrite pipeline, directly
contributing to BOLT's RSS peak. I did a fair amount of digging and
didn't find any reason as to why we need to keep all DIEs of DWO CU
materialized at all, since DWARFRewriter won't even read this vector
(the llvm#197359 concurrency fix did use that, but that is unnecessary). The
problem is that these DIE trees are a massive contribution to RSS when
processing large binaries where we have 10s of K of dwos, storing
complete trees for each processed dwo.

This diff changes the llvm#197359 concurrency fix to not rely on the DIE
sibling/children structure. It parses DWP type units selectively per
compile unit (DIEBuilder::buildDWPTypeUnitsForUnit ->
collectReferencedTypeSignatures) by finding the DW_FORM_ref_sig8
references in a unit's DIEs to decide which type units belong in that
unit's output .dwo. That walk previously used DWARFDie::children(),
which requires the unit's full DIE vector. Here we rewrite the walk to
stream the unit's DIEs one at a time with
DWARFDebugInfoEntry::extractFast (the same technique already used by
DIEBuilder::constructFromUnit and DWARFRewriter::partitionCUs), reading
DW_FORM_ref_sig8 attributes off a single reusable transient entry. The
tree structure is irrelevant -- every DIE in the unit is visited
regardless -- so no DIE vector is
built. collectReferencedTypeSignatures now takes a DWARFUnit& instead of
a DWARFDie.

With the walk self-sufficient:
- preprocessDWODebugInfo() now extracts only the .dwo CU DIE
(getNonSkeletonUnitDIE(true)); nothing reads the full array off it
anymore (constructFromUnit and the signature walk both stream).
- BinaryContext::collectDebugScopeBoundaries() drops its split-DWARF
fast-path, which called DWARFUnit::dies() (= full extraction); DWO units
are now streamed like monolithic ones.

The result is that .dwo DIE vectors are never materialized during BOLT
processing.

Expected to be a ~10% RSS win on large split-dwarf binaries.

Depends on llvm#207291
This should improve timezone coverage for keeping the bazel build
working due to libc breakages, e.g. llvm#209433 broke things and the bazel
fixer bot sent out llvm#209689. But since it wasn't landed until just
recently, manual fixes were needed for other changes like llvm#209449. This
wouldn't be as bad if the bazel fixer bot could handle layered
breakages.
…m#211995)

This patch implements contains(StringRef) and contains(uint64_t) in
SampleProfileNameTable and SampleProfileReader to serve symbol
membership queries directly from the reader -- "is this symbol in the
name table?".

Without this patch, users of the sample profile reader, namely
SampleProfileLoader::doInitialization and SampleProfileNameSet, each
construct their own StringSet<> containing all name table entries.
That is, we end up with two instances of StringSet<> with identical
contents.  Since these instances hold their own copies of symbol
strings on the heap, both the constructor and destructor take up a
large portion of compilation time.

This patch teaches SampleProfileReader::contains to directly serve
symbol membership queries.

- For EytzingerSampleProfileNameTable, contains performs binary search
  directly across the three concatenated Eytzinger table spans
  (CSKeys, FlatKeys, and Inlinees) in a cache-friendly manner.

- Other representations of the name table lazily construct an internal
  DenseSet on demand.

This patch updates existing customers to call Reader->contains.

RFC:
https://discourse.llvm.org/t/rfc-faster-sample-profile-loading/90957/8

Assisted-by: Antigravity
…llvm#212445)

Previously, `-NOT` checks were not doing what was intended: checking
that given strings are not present within the same line where other
patterns are confirmed present by other checks. `-NOT` semantics is
checking pattern absense in between other checks, not total absense.

This patch makes use of `--implicit-check-not` instead for this purpose.
…0179)

Common globals were not emitted in GOFF object files due to a missing
emitCommonSymbol implementation. This adds the implementation to emit
the required SD/ED/PR ESD records in the GOFF object file.
When a code block in the documentation contains (almost) pseudocode, the
Pygments parser flags errors and renders them with red-bordered boxes.
This is unnecessarily ugly. We can see examples of this in the LangRef
with LLVM code blocks.

Instead set the style to just render them as plain text. This is still
recognizable as incorrect syntax, but does not distract the reader from
the actual example.

Assisted-by: Claude Opus 4.8
Flatten associative single-use chains like ((a+b)+c)+d into one N-ary
tree node instead of nested 2-operand entries, so vectorizable operand
groupings (consecutive loads, broadcasts) spanning the whole chain
aren't hidden by the nesting. The flattened layout is kept only when it
scores better than the natural 2-operand shape. Codegen combines the
columns pairwise, reusing a scalar's IR flags where a combine step
reproduces it exactly and dropping nsw/nuw/nnan/ninf otherwise, since
regrouping can change what may overflow or produce NaN/Inf. Controlled
by the hidden -slp-reassociate-ops flag (default on).

Reviewers: bababuck, RKSimon, hiraditya

Pull Request: llvm#208514
Defines the `SemanticSignatureElement` struct in
`llvm/Frontend/HLSL/SemanticSignatures` to represent a semantic
signature in-memory for use during packing and metadata
construction/parsing.

Adds unit testing of the conversion.

Resolves: llvm#204878

Assisted by: Claude Opus 4.8
A computed `goto *p` placed inside a nested scope -- an if or a loop
body --
made CIRGen produce invalid IR that the region verifier rejected with
"reference to block defined in another region", aborting the compile.
Regular
`goto` avoids this because CIRGen emits a symbolic
`cir.goto` that references no block and is later resolved into a
`cir.br` by
GotoSolver, which runs after FlattenCFG has merged the nested scopes
into one
region. Indirect goto skipped that indirection: `emitIndirectGotoStmt`
built
a real indirect-branch block during CIRGen and branched to it from
inside the
nested region, and `finishIndirectBranch` wired the `cir.indirect_br`
successors at the end of the function -- both while the scopes were
still
separate regions.

This gives indirect goto the same symbolic treatment.  A new terminator,
`cir.indirect_goto`, carries the target address and references no
successor,
so it is valid in any region.  GotoSolver now rewrites each one into a
`cir.br` to a single shared block holding the `cir.indirect_br` over
every
address-taken label; running after FlattenCFG, it sees all blocks in one
region, so the cross-region branch can no longer occur. GotoSolver
already
collects the address-taken labels -- from `cir.block_address` ops and
from
block-address attributes in global initializers -- so the CIRGen-side
bookkeeping it supersedes (the lazily-built indirect-goto block, the
per-function target list, and the `CIRGenModule` block-address-to-label
map)
is removed.

An indirect goto that branches out of a scope needing cleanup (a VLA
stack
restore, or a non-trivial destructor on the edge) must run that cleanup
on the
branch, which this does not implement.  Rather than emit a branch that
silently skips the cleanup, `emitIndirectGotoStmt` reports it with
`errorNYI`.

With the fix, the `evalloop`, `20041214-1`, and `comp-goto-1` programs
in the
LLVM test-suite go from a CIRGen crash to building and running.
…uire implicit derivatives (llvm#212846)

This PR adds availability attributes to texture sample methods that
require implicit derivatives (fixes
llvm#198885)

To make these availability attributes actually get checked,
`DiagnoseHLSLAvailability::HandleFunctionOrMethodRef` in `SemaHLSL.cpp`
has been changed to check availability attributes regardless of whether
or not a function has a body/definition (fixes
llvm#212842).

Assisted by: Claude Opus 5
This introduces a new CIR attribute that will be used to describe
floating-point environment assumptions and restrictions, allowing for
general modeling of floating-point environment access. A new interface
is also introduced to simplify handling of default settings when the
attribute or one of its optional components is not present.

This patch adds the attribute and interface to FPBinaryOp,
BinaryFPToFPBuiltinOp, and UnaryFPToFPBuiltin. Support for generating
operations with this attribute and lowering them to the LLVM dialect
will be added in a future change.

Assisted-by: Cursor / claude-opus-4.8
…meout (llvm#212574)

The test evaluates an expression that forks a child which returns
normally (triggering SIGTRAP from the JIT wrapper trap at _start). The
parent blocks in waitpid() until the detached child terminates. With the
default 250ms expression timeout, the kernel sometimes doesn't schedule
the detached child fast enough, causing waitpid() to still be blocking
when the timeout fires and the expression gets interrupted.

Set a 5-second expression timeout to give the kernel ample time to
schedule the detached child process.
…1368)

This showed up doing a self-build of MLIR's Presburger
IntegerRelation.cpp, which is a bit pathalogical. It resulted in us
doing a lot of rewrite patterns during flatten, taking about 20s. After
this patch, we're down to sub-1s spent doing that.

This is because applyOpPatternsGreedily was re-enqueing every child
opops every time we modified anything nearby. This caused us in cases
where there were operations that were visited TONS of times just because
a parent got modified.

This patch replaces this with a very simple inside-out iteration of
these operations. The recent loop-op 'cleanup' flattening modification
necessitates us re-visiting these sometimes (hence the loop).

This patch is effectively 'NFC' other than build time, so there really
isn't a test I could write.

AI: Note: I've used Claude Opus 4.8 to help me with this patch. I've
read/attempted to comprehend as much of this as possible, but I'm still
pretty inexperienced as to how to manage passes/etc. Claude promises me
this is the best way, and I haven't been able to find anything better
grepping around other transformations in other projects, but please
comment if you have a better idea!
This builtin is a no-op (just a load/store) if we don't have reassociate
turned on. This patch implements the 'easy' path to unblock libraries
that use this builtin.
…#212451)

Make sure -march and -mcpu both error for nonoffload and for
-Xopenmp-target arguments. Defends against regression I almost
introduced.
`llvm-mc -triple arm64-*` requires aarch64-registered-target.
@ronlieb
ronlieb requested review from ftynse and kuhar as code owners July 29, 2026 23:06
@ronlieb
ronlieb requested review from a team, dpalermo and skganesan008 July 29, 2026 23:06
@ronlieb
ronlieb merged commit 7f80a9e into amd-staging Jul 30, 2026
159 of 164 checks passed
@ronlieb
ronlieb deleted the amd/merge/upstream_merge_20260729164548 branch July 30, 2026 03:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.