[mlir][arith][llvm] Mark floordivsi/urem/srem as ConditionallySpeculatable (#235770)
These ops can trap (division/remainder by zero, and signed overflow for
the signed variants). They were incorrectly marked `Pure`, which allowed
LICM to hoist them out of loops that may execute zero times.
This change makes them `ConditionallySpeculatable`, following the same
pattern already used by `divsi`/`remsi` and `udiv`/`sdiv`.
Fixes #233213
Related discussion:
https://discourse.llvm.org/t/ub-op-semantics-of-arith-integer-division-remainder/92558
---------
Co-authored-by: Matthias Springer <me at matthiasspringer.de>
[SPIRV] Emit NSDI opcode DebugTypeEnum (#234752)
This makes `SPIRVNonSemanticDebugHandler` emit
[`DebugTypeEnum`](https://github.khronos.org/SPIRV-Registry/nonsemantic/NonSemantic.Shader.DebugInfo.html#DebugTypeEnum)
for a `DICompositeType` tagged `DW_TAG_enumeration_type`, with one Value
and Name pair per `DIEnumerator`. Each CU lists its file-scope enums in
`enums:`. Each of those enums takes that compile unit as its Parent.
Three operands need special handling:
1. Underlying Type: an enum declared without a type, such as `enum E { A
}`, defaults to `int`, so this emits `int` rather than `DebugInfoNone`.
2. Size must be an `OpConstant`, so an incomplete enum, whose size is
recorded as 0, is dropped.
3. Each Value is a 32-bit integer `OpConstant`. If an enumerator needs
more bits, we leave it out.
This does not handle cycles, such as a struct with a member of an enum
declared inside it. [PR
[10 lines not shown]
[mlir][OpenMP] Diagnose non-loop-transformation uses of omp.new_cli (#235164)
The verifier assumed every user of the CLI implements
LoopTransformationInterface, so it asserted on other operations such as
func.call.
Replaced the cast with dyn_cast so the verifier emits an error pointing
at the invalid use instead, and added a test.
Fixes #234635
[libcxx][test-support] Implement fancy_pointer_allocator (#196187)
In order to make sure that our further modifications of basic_string
will make it able to handle fancy pointers such as boost::ipc::offset_ptr,
we need some testable fancy pointers. Unfortunately, offset pointers
themselves are a bad idea for that, as they cannot be constant evaluated.
Instead, we are implementing a test fancy pointer that has nontrivial
special member functions that are C++20 constexpr and have side effects
that can be checked on correctness even in constant evaluated test contexts,
backed by a similarly C++20 constexpr fancy pointer allocator.
The idea is that the allocator has a state that counts how many pointer
instances originated from the allocator exist at the moment, the
pointers in their special methods update this shared state, and the
state checks at its destruction that there exactly 0 pointers are recorded
as still existing. The state is unique per instance of default-constructed
allocator but shared between the instances of copy/move-constructed
allocators.
[10 lines not shown]
feat(gisel): Mirror trunc/xor/select demanded bits
Extend scalar demanded-bits simplification to G_TRUNC, G_XOR, and
G_SELECT, following SelectionDAG traversal, known-bit propagation,
shared-use handling, and final folds. Honor GISel legality and target
profitability when rewriting or narrowing operations.
Share AArch64's logical-immediate search through a narrow XOR hook and
adapt XOR/shift profitability queries for both selectors. Preserve
SelectionDAG's constant-shrinking interface and node construction.
Share shift-amount validation in CodeGenCommonISel using templated
callbacks for selector-specific lane access and KnownBits queries.
Preserve recursive constant bypasses and use-specific rewrites of shared
producers. Recognize constants at the analysis depth limit, matching
SelectionDAG, and retain KnownBits-based bypasses as a fallback.
Keep G_ASHR of G_SEXT_INREG arithmetic unless the top C + BW - W bits are
[5 lines not shown]
[mlir] Preserve all analyses in reconcile-unrealized-casts when no casts (#236336)
This lets the pass manager skip the post pass verifier, visible on large
modules
Without casts the pass changes nothing, so re-verifying the whole module
is a waste of time
[mlir][shard] Fix FoldDuplicateShardOp assertion on duplicates in different blocks (#232953)
`FoldDuplicateShardOp` looks for another `shard.shard` of the same value
and checks `otherOp->isBeforeInBlock(op)` to decide which one is the
duplicate. `isBeforeInBlock` asserts when the two ops are not in the
same block, so a value that is annotated once in the function body and
once inside a region (for example a `linalg.generic` or `scf.if` body)
crashes `--canonicalize`:
```
Operation.cpp:382: bool mlir::Operation::isBeforeInBlock(mlir::Operation *): Assertion `other && other->block == block && "Expected other operation to have the same parent block."' failed.
```
The pattern was written for the same-block duplicates that sharding
propagation produces, so just skip the fold when the other op lives in a
different block. Both annotations stay in place, which is always valid.
Adds a canonicalization test with a duplicate inside an `scf.if` region.
[2 lines not shown]
[IndVarSimplify] Use context to prove a narrow IV def non-negative
When IndVars widens an IV, it checks for each narrow def
(the IV and values computed from it) whether it is
non-negative on every iteration.
If it is, zext and sext of it are equal. Then when IndVars
idens the def's users, they can choose to use either
the sext or zext of the def.
Previously, we didn't use context to prove the non-negativity of def.
Now ask SCEV about the def non-negativity at its context -
the def instruction itself.
This allows SCEV to infer facts from the dominating guards and assumes.
This in turn allows eliminating unnecessary truncs/zexts. E.g. in
if (m > 0)
[9 lines not shown]
[AVR] Introduce AVRCodeGenPassBuilder
Mostly mirrors the existing TargetPassConfig. This is for supporting the
NewPM which will eventually replace the LegacyPM.
Reviewers: arsenm, benshi001
Pull Request: https://github.com/llvm/llvm-project/pull/236244
[AMDGPU] Fix invalid CFI when a prologue copies a register to a VCC half (#236119)
A prologue can save the frame pointer or base pointer by copying it to
an unused SGPR, and that SGPR can be vcc_lo or vcc_hi. Their DWARF
register numbers, VCC_32_LO (512) and VCC_32_HI (513), are only defined
in wave32, so in wave64 the CFI named registers that do not exist there.
In wave64, describe the copy as a 32-bit lane of VCC_64 instead.
Assissted By: Cursor
[lldb] Skip debugInfo modules in stats without IncludeModules (#236412)
GetStatistics got every module's symbol file path and debug info modules
unless only a summary was requested.
They arere only reported if the `IncludeModules` option is enabled.
Without `IncludeModules` they were computed and dropped.
Only get them when modules are included.
[flang][OpenMP] Implement LOCAL_INIT support in do concurrent to OpenMP conversion (#234925)
Implement conversion of the Fortran `LOCAL_INIT` locality specifier to OpenMP in the `DoConcurrentConversion` pass. Previously, encountering `LOCAL_INIT` would hit a `TODO` and abort compilation. This PR removes that `TODO` and implements correct per-iteration initialization semantics.
Fortran's `LOCAL_INIT` locality specifier requires that at the start of **each iteration** of a `do concurrent` loop, the private variable is re-initialized from the host (original) variable. The naive approach of mapping this to OpenMP's `firstprivate` (i.e., placing the copy in `omp.private`'s `copy_region`) is incorrect because that would set up the local copy once per thread but not once per iteration as required by `LOCAL_INIT`
The solution in this PR mirrors what `SimplifyFIROperations` already does for the
non-OpenMP path:
1. **Privatizer creation**: `LOCAL_INIT` creates the same `omp.private {type = private}` as `LOCAL` — with `init` and `dealloc` regions but **no `copy_region`**. This gives each thread its own storage.
2. **Per-iteration copy inlining**: The `fir.local` op's `copy_region` operations are inlined at the top of the `omp.loop_nest` body, so re-initialization happens every iteration. This is done via a new `inlineCopyRegionToLoopBody()` helper that clones the copy_region ops one-by-one using an `IRMapping`, substituting the region's block arguments with the original variable and the private block arg.
The inlining happens in `matchAndRewrite()` after block argument remapping (where stale `fir.do_concurrent.loop` block args are replaced with the final `omp.wsloop`/`omp.parallel` block args), ensuring the correct SSA values are used.
Generated IR (host path)
------------------------
[21 lines not shown]
[NVPTX] add truncating store action for v2i32 to v2i1 (#235390)
expand action for `v2i32` to `v2i1` truncating stores was never set, so
they hit a scalar-only path in `LegalizeStoreOps` and crashed.
added it and the repro as a test.
fixes #235365.
[IndVarSimplify] Use context to prove a narrow IV def non-negative
When IndVars widens an IV, it checks for each narrow def (the IV and
values computed from it) whether it is non-negative on every iteration.
If it is, zext and sext of it are equal. Then when IndVars widens IV's
users, they can use both the sext and zext of it.
Now ask SCEV about def non-negativity using its context.
This allows it to infer facts from the dominating guards and assumes.
Assisted-By: Claude
[IndVarSimplify][SCEV][NFC] Add tests for LFTR losing the constant max trip count
When IndVars rewrites a loop exit like i >s C, where i starts at a
variable start, to i + 1 == smax(start, C + 1), SCEV's constant max
backedge-taken count of the loop gets worse: C - SINT_MIN before the
rewrite, all ones after it.
Add tests where those counts could be improved.
Assisted-By: Claude
fix(gisel): Keep ashr of sext_inreg and update checks
G_TRUNC roots now pass narrowed demand into the G_ASHR case, which turned
ashr(sext_inreg X, W), C into lshr whenever the top C bits were
undemanded. SelectionDAG folds that pair into a single sra by C + BW - W
before the same check, so it keeps the arithmetic shift. Use the folded
amount here too. This keeps AArch64 sbfx selection (neon-dotreduce.ll and
sext.ll no longer churn).
Regenerate the remaining AArch64 and AMDGPU checks affected by the new
TRUNC/XOR/SELECT roots.
[Offload][Omp] Compute getBlockLimit through liboffload (#236400)
Add two new device properties accessible through liboffload:
LAUNCH_MAX_NUM_WORK_GROUPS (max blocks) and LAUNCH_MAX_GRID_SIZE (max
total work-items). Using them compute the getBlockLimit in libomptarget
in a backend agnostic way.
Remove getBlockLimit from the Plugin Interface as it's no longer needed.
Assisted by Claude.