9427 Commits

Author SHA1 Message Date
Matt Arsenault
253ed52436
DAG: Use poison for some vector result widening (#168290) 2025-11-19 16:49:43 -05:00
Joshua Rodriguez
4353845838
[AArch64][GlobalISel] Added support for hadd family of intrinsics (#163985)
GlobalISel now selects hadd family of intrinsics, without falling back
to SDAG.
2025-11-19 15:44:02 +00:00
Philip Ginsbach-Chen
bdcaa0001a
[AArch64] match TRN starting from undef elements (#167955)
When the first element of a trn mask is undef, the `isTRNMask` function
assumes `WhichResult = 1`. That has a 50% chance of being wrong, so we
fail to match some valid trn1/trn2.

This patch introduces a more precise test to determine the correct value
of `WhichResult`, based on corresponding code in the `isZIPMask` and
`isUZPMask` functions.

- This change is based on #89578. I'd like to follow it up with a
further change along the lines of #167235.
2025-11-19 12:53:12 +00:00
Ryan Cowan
58e6d02aa2
[AArch64][GlobalISel] Check unmergeSrc is a vector in matchCombineBuildUnmerge (#168692)
This aims to fix the crash in #168495, my combine rule was
missing a check that the source vector was in fact a vector. This then
caused the legality check to fail in this example as the concat was
trying to concat a non vector.

I have also gated the bitcast of the concat to only work on non-scalable
vectors as the mutation calls `getNumElements` which crashes when called
on a scalable vector.

Fixes #168495
2025-11-19 12:30:51 +00:00
Marius Kamp
94e9bfb803
[AArch64] Reorder Comparison Trees to Facilitate CSE (#168064)
The AArch64 backend converts trees formed by conjunctions/disjunctions
of comparisons into sequences of `CCMP` instructions. The implementation
before this change checks whether a sub-tree must be processed first. If
not, it processes the operations in the order they occur in the DAG.

This may not be optimal if there is a corresponding `SUB` node for one
of the comparisons. In this case, we should process this comparison
first because we can then use the same instruction for the `SUB` node
and the comparison.

To achieve this, this commit comprises the following changes:

- Extend `canEmitConjunction` with a new output parameter `PreferFirst`,
  which reports to the caller whether the sub-tree should preferably be
  processed first.
- Set `PreferFirst` to `true` if we can find a corresponding `SUB` node
  in the DAG.
- If we can process a sub-tree with `PreferFirst = true` first (i.e., we
  do not violate any `MustBeFirst` constraint by doing so), we swap the
  sub-trees.
- The already existing code for performing the common subexpression
  elimination takes care to use only a single instruction for the
  comparison and the `SUB` node if possible.

Closes #149685.
2025-11-18 17:36:18 +00:00
Nathan Corbyn
93a8ca8fc7
[AArch64][GISel] Don't crash in known-bits when copying from vectors to non-vectors (#168081)
Updates the demanded elements before recursing through copies in case
the type of the source register changes from a non-vector register to a
vector register.

Fixes #167842.
2025-11-18 16:42:58 +00:00
Hassnaa Hamdi
3d5d32c605
[CGP]: Optimize mul.overflow. (#148343)
- Detect cases where LHS & RHS values will not cause overflow
(when the Hi halfs are zero).
2025-11-18 13:15:47 +00:00
Paul Walker
59ed6dfe97
[LLVM][CodeGen][SVE] Use DUPM for constantfp splats. (#168391)
This helps cases where the immediate range of FDUP is not sufficient.
2025-11-18 12:15:38 +00:00
David Green
4ecfaa602f
[AArch64][GlobalISel] Add better basic legalization for llround. (#168427)
This adds handling for f16 and f128 lround/llround under LP64 targets,
promoting the f16 where needed and using a libcall for f128. This
codegen is now identical to the selection dag version.
2025-11-18 12:05:02 +00:00
Sander de Smalen
f369a53d82
[DAGCombiner] Fold select into partial.reduce.add operands. (#167857)
This generates more optimal codegen when using partial reductions with
predication.

```
partial_reduce_*mla(acc, sel(p, mul(*ext(a), *ext(b)), splat(0)), splat(1))
-> partial_reduce_*mla(acc, sel(p, a, splat(0)), b)

partial.reduce.*mla(acc, sel(p, *ext(op), splat(0)), splat(1))
-> partial.reduce.*mla(acc, sel(p, op, splat(0)), splat(trunc(1)))
```
2025-11-18 09:49:42 +00:00
Benjamin Maxwell
603ac57ef9
[AArch64][SME] Add support for zeroing ZT0 to CommitZASavePseudo (#166360)
This will be used to support ZT0 in the MachineSMEABIPass.
2025-11-18 09:26:21 +00:00
Eli Friedman
5ba8579312
[Arm64EC] Preserve X9 for indirect calls. (#167782)
Arm64EC indirect calls use a function __os_arm64x_check_icall... this
has one obvious return value, x11, which is the function to call.
However, it actually returns one other important value: x9, which is the
final destination for the emulator after the call. If the call is
calling x64 code, x9 is used by the thunk.

Previously, we didn't model this, and it mostly worked because the
compiler usually doesn't modify x9 in the narrow window between the
check, and the call. That said, it can happen in some cases; one
reliable way is to do an indirect tail-call with stack protectors
enabled. (You can also just get unlucky with register allocation, but
it's harder to write a testcase for that.)

This patch uses the cfguardtarget bundle to simplify the calling
convention handling, for similar reasons that x64 uses it: modifying
arbitrary calls is difficult without a separate marking.

Fixes #167430.
2025-11-17 16:24:40 -08:00
Guy David
7d0a2082bf
[AArch64] Treat COPY between cross-register banks as expensive (#167661)
The motivation is to allow passes such as MachineLICM to hoist trivial
FMOV instructions out of loops, where previously it didn't do so even
when the RHS is a constant.
On most architectures, these expensive move instructions have a latency
of 2-6 cycles, and certainly not cheap as a 0-1 cycle move.
2025-11-18 00:05:54 +02:00
David Green
21e0b56d7a [AArch64][GlobalISel] Add basic GISel test coverage for lround and llround. NFC 2025-11-17 19:47:36 +00:00
Guy David
69b4190d5f
[AArch64] Optimize extending loads of small vectors (#163064)
Reduces the total amount of loads and the amount of moves between SIMD
registers and general-purpose registers.
2025-11-17 21:39:10 +02:00
Ryan Cowan
d65be16ab6
[AArch64][GlobalISel] Add combine for build_vector(unmerge, unmerge, undef, undef) (#165539)
This PR adds a new combine to the `post-legalizer-combiner` pass. The
new combine checks for vectors being unmerged and subsequently padded
with `G_IMPLICIT_DEF` values by building a new vector. If such a case is
found, the vector being unmerged is instead just concatenated with a
`G_IMPLICIT_DEF` that is as wide as the vector being unmerged.

This removes unnecessary `mov` instructions in a few places.
2025-11-17 15:55:40 +00:00
David Green
22968f5b4a
[DAG] Add strictfp implicit def reg after metadata. (#168282)
This prevents a machine verifier error, where it "Expected implicit
register after groups".

Fixes #158661
2025-11-17 10:57:21 +00:00
David Green
19c1381662
[AArch64][GlobalISel] Fix vecreduce(zext) fold from illegal types. (#167944)
We generate a ADDLV node that incorporates a vecreduce(zext) from
elements of half the size. This means that we need the input type to be
at least twice the size of the input.

I updated some variable names whilst I was here.

Fixes #167935
2025-11-17 10:52:59 +00:00
hstk30-hw
51c8180515
[GlobalMerge]Prefer use global-merge-max-offset instead of the target-specific constant offset. (#165591)
In the Dhrystone benchmark, I find some adjacent global not be merged,
on the contrary the GCC's anchor optimize is work. Use
global-merge-max-offset to set the max offset can yield similar results
(still slightly different, at least we can control the offset).
2025-11-17 15:37:51 +08:00
Simon Pilgrim
8a055f8067
[DAG] Add baseline test coverage for #161036 (#168278)
Baseline tests from #161651 that were reverted in #167854

Still missing test coverage for the ffmpeg regression failures
2025-11-16 17:00:24 +00:00
Alex Bradbury
be9e287b04
[AArch64][test] Improve pr166870.ll test case (#168194)
As pointed out in post-commit discussion on #167336
<https://github.com/llvm/llvm-project/pull/167336#issuecomment-3523794206>,
although the test case succeeds in showing a codegen difference now the
faulty MachineCopyPropagation logic was removed, the example was reduced
so much that it actually would have been legal to remove the seemingly
redundant mov.

This is a re-reduction of that test case which should now demonstrate a
mov that can't safely be removed (mov w9, w9) because the upper bits no
longer being zeroed may alter the program logic.
2025-11-16 11:09:00 +00:00
AZero13
d831f8df52
[SelectionDAG] Fix AArch64 machine verifier bug when expanding LOOP_DEPENDENCE_MASK (#168221)
TargetConstant nodes don't match TableGen ImmLeaf patterns during
instruction selection. When this zero constant flows into the AArch64
CCMP formation code, the machine verifier hits an assertion in expensive
checks.

Fixes: #168227
2025-11-15 21:12:11 +00:00
Ryan Cowan
f8d65fd874
[AArch64][GlobalISel] Improve lowering of vector fp16 fpext (#165554)
This PR improves the lowering of vectors of fp16 when using fpext.

Previously vectors of fp16 were scalarized leading to lots of extra
instructions. Now, vectors of fp16 will be lowered when extended to fp64
via the preexisting lowering logic for extends. To make use of the
existing logic, we need to add elements until we reach the next power of
2.
2025-11-14 20:52:51 -08:00
David Tellenbach
0363bd8165
[AArch64][FEAT_CMPBR] Codegen for Armv9.6-a CBB and CBH (#164899)
This patch adds codegen for CBB and CBH, CB variants operating on bytes
and half-words, allowing to fold sign- and zero-extensions.

Since if-conversion needs to be able to undo conditional branches, we
remember possibly folded zero- and sign-extensions, as well as
potentially folded assertzext and assertsext as additional
arguments of the CBBAssertExt and CBHAssertExt pseudos during codegen.
2025-11-14 21:46:59 +00:00
Shubham Sandeep Rastogi
44b94a4f75
[AArch64][DebugInfo]Add Target hooks for InstrRef on AArch64 (#165953)
This patch adds the target hooks required by Instruction Referencing for
the AArch64 target, as mentioned in
https://llvm.org/docs/InstrRefDebugInfo.html#target-hooks

Which allows the Instruction Referenced LiveDebugValues Pass to track
spills and restore instructions.

With this patch we can use the
`llvm/utils/llvm-locstats/llvm-locstats.py` to see the coverage
statistics on a clang.dSYM built with in RelWithDebInfo we can see:

coverage with dbg_value:
```
=================================================
            Debug Location Statistics       
 =================================================
     cov%           samples         percentage(~)  
 -------------------------------------------------
   0%              5828021               38%
   (0%,10%)         127739                0%
   [10%,20%)        143344                0%
   [20%,30%)        172100                1%
   [30%,40%)        193173                1%
   [40%,50%)        127366                0%
   [50%,60%)        308350                2%
   [60%,70%)        257055                1%
   [70%,80%)        212410                1%
   [80%,90%)        295316                1%
   [90%,100%)       349280                2%
   100%            7313157               47%
 =================================================
 -the number of debug variables processed: 15327311
 -PC ranges covered: 67%
 -------------------------------------------------
 -total availability: 62%
 =================================================
 ```
 
coverage with InstrRef without target hooks fix:
```
 =================================================
            Debug Location Statistics       
 =================================================
     cov%           samples         percentage(~)  
 -------------------------------------------------
   0%              6052807               39%
   (0%,10%)         127710                0%
   [10%,20%)        129999                0%
   [20%,30%)        155011                1%
   [30%,40%)        171206                1%
   [40%,50%)        102861                0%
   [50%,60%)        264734                1%
   [60%,70%)        212386                1%
   [70%,80%)        176872                1%
   [80%,90%)        242120                1%
   [90%,100%)       254465                1%
   100%            7437215               48%
 =================================================
 -the number of debug variables processed: 15327386
 -PC ranges covered: 67%
 -------------------------------------------------
 -total availability: 60%
 =================================================
 ```
 
coverage with InstrRef with target hooks fix:
```
 =================================================
            Debug Location Statistics       
 =================================================
     cov%           samples         percentage(~)  
 -------------------------------------------------
   0%              5972267               39%
   (0%,10%)         118873                0%
   [10%,20%)        127138                0%
   [20%,30%)        153181                1%
   [30%,40%)        170102                1%
   [40%,50%)        102180                0%
   [50%,60%)        263672                1%
   [60%,70%)        212865                1%
   [70%,80%)        176633                1%
   [80%,90%)        242403                1%
   [90%,100%)       264441                1%
   100%            7494527               48%
 =================================================
 -the number of debug variables processed: 15298282
 -PC ranges covered: 71%
 -------------------------------------------------
 -total availability: 61%
 =================================================
 ```
 
 I believe this should be a good indication that Instruction Referencing should be turned on for AArch64?
2025-11-14 10:36:47 -08:00
Jonathan Thackray
8cc93c490d
[AArch64] Remove FEAT_TME assembly and ACLE support (#167687)
The Transactional Memory Extension (TME) was introduced as part of
Armv9-A but has not been adopted by the ecosystem. This mirrors what
Arm has observed with similar extensions in other architectures.

Therefore, remove FEAT_TME assembly and ACLE code from llvm, because
support for TME has now been officially withdrawn, as noted here:

```
   FEAT_TME is withdrawn from all future versions of Arm®
   Architecture Reference Manual for A-profile architecture.
```

referenced in Known Issue D24093, documented here:
   https://developer.arm.com/documentation/102105/lb-05/
2025-11-14 12:11:55 +00:00
Benjamin Maxwell
c021e168b3
[AArch64][SME] Handle SME state around TLS-descriptor calls (#155608)
This patch ensures we switch out of streaming mode before TLS-descriptor
calls. ZA state will also be preserved when using the new SME ABI
lowering (`-aarch64-new-sme-abi`).

Fixes #152165
2025-11-14 10:50:26 +00:00
Pierre van Houtryve
31b7f1fa0b
[GlobalISel] Add support for value/constants as inline asm memory operand (#161501)
InlineAsmLowering rejected inline assembly with memory reference inputs
if the values passed to the inline asm weren't pointers. The DAG
lowering however handled them just fine.

This patch updates InlineAsmLowering to store such values on the stack,
and then use the stack pointer as the "indirect" version of the operand.
2025-11-14 10:34:38 +01:00
David Green
50f16ff748
[AArch64] Make the list of outline atomic supported operations explicit (#167760)
As new operations are added (for example uinc_wrap, udec_wrap,
usub_cond, usub_sat), they will not automatically be supported by
outline atomics and so should be expanded by the pre-isel pass. Make the
list of supported outline atomics explicit to make sure we only mark the
expected intrinsics as outline atomics.

Fixes #167728
2025-11-13 18:05:08 +00:00
Benjamin Maxwell
12322b22c6
[AArch64][SVE] Allow basic use of target("aarch64.svcount") with +sve (#167875)
This prevents the backend from crashing for basic uses of __SVCount_t
type (e.g., as function arguments), without +sve2p1 or +sme2.
    
Fixes #167462
2025-11-13 16:33:18 +00:00
AZero13
e5baf073cb
[AArch64] Generalize CSEL a, b, cc, SUBS(SUB(x,y), 0) -> CSEL a, b, cc, SUBS(x,y) transform to peephole (#167527)
This transform should have never been done in ISel in the first place.
It should have been done in peephole, but a few cases were missing.
2025-11-13 13:36:14 +00:00
Sander de Smalen
5fa3ccb04f
[AArch64] Use SVE fdot for partial.reduce.fadd for NEON types. (#167856)
We only seem to use the SVE fdot for fixed-length vector types when they
are larger than 128bits, whereas we can also use them for 128bits
vectors if SVE2p1/SME2 is available.
2025-11-13 10:50:29 +00:00
Simon Pilgrim
a5342d5fe5
Revert "[DAG] Fold (umin (sub a b) a) -> (usubo a b); (select usubo.1 a usubo.0)" (#167854)
Reverts llvm/llvm-project#161651 due to downstream bad codegen reports
2025-11-13 10:46:38 +00:00
Matt Arsenault
782759b757
DAG: Use poison when widening build_vector (#167631)
Test changes are mostly noise. There are a few improvements and a few
regressions.
2025-11-12 20:17:41 +00:00
Matt Arsenault
0385a182da
DAG: exp opcodes cannotBeOrderedNegativeFP (#167604) 2025-11-12 19:50:46 +00:00
Matt Arsenault
201a461bb9
AArch64: Add baseline test for treating exp as known positive (#167603) 2025-11-12 10:46:23 -08:00
Chaitanya Koparkar
1f58cbe60a
[DAG] Fold (umin (sub a b) a) -> (usubo a b); (select usubo.1 a usubo.0) (#161651)
Fixes #161036.
2025-11-12 14:38:21 +00:00
Sander de Smalen
07cd105416 [AArch64] Add 'REQUIRES: asserts' to regalloc-hint-movprfx.mir
This should fix the buildbot failure reported here:

  https://lab.llvm.org/buildbot/#/builders/11/builds/27869
2025-11-12 12:17:29 +00:00
Paul Walker
46e9d6325a
[LLVM][CodeGen][SVE] Use BFMLALB for promoted bfloat fma operations. (#167340)
We're likely to get better code from custom legalisation, where we can
remove unpack instructions (plus SVE2p1 has BFMLSLB/T), but we get much
of benefit with these two small changes.

NOTE: LLVM has no support for FEAT_AFP in terms of feature detection or
ACLE builtins, so the compiler works under the assumption the feature is
not enabled.

Patch is also more aggressive when enabling bfloat fma construction
because it removes unnecessary rounding which is generally preferable
regardless of whether BFMLALB is used or not.
2025-11-12 11:46:14 +00:00
Benjamin Maxwell
cf51a5e872
[AArch64][SME] Enable split SVE for hazard padding in SVE CC functions (#166561)
This patch enables `aarch64-split-sve-objects` to handle hazard padding
in functions that use the SVE CC even when there are no predicate
spills/locals.

This improves the codegen over the base hazard padding implementation,
as rather than placing the padding in the callee-save area, it is placed
at the start of the ZPR area.

E.g., Current lowering:

```
sub sp, sp, #1040
str x29, [sp, #1024] // 8-byte Folded Spill
addvl sp, sp, #-1
str z8, [sp] // 16-byte Folded Spill
sub sp, sp, #1040
```

New lowering:

```
str x29, [sp, #-16]! // 8-byte Folded Spill
sub sp, sp, #1024
addvl sp, sp, #-1
str z8, [sp] // 16-byte Folded Spill
sub sp, sp, #1040
```

This also re-enables paired stores for GPRs (as the offsets no longer
include the hazard padding).
2025-11-12 10:58:05 +00:00
Sander de Smalen
fe8865c468
[AArch64] Prioritize regalloc hints over movprfx hints (#167480)
This is a follow-up from #166926 that ensures the hints are only added
once, and ensures that hints inserted by the register allocator take
priority over hints to reduce movprfx.
2025-11-12 08:44:21 +00:00
Saleem Abdulrasool
2d8563f4b8
AArch64: align pair-wise spills on WoS to 16-byte (#166902)
Adjust the frame setup code for Windows ARM64 to attempt to align
pair-wise spills to 16-byte boundaries. This enables us to properly emit
the spills for custom clang calling convensions such as preserve most
which spills r9-r15 which are normally nonvolatile registers. Even when
using the ARM64EC opcodes for the unwinding, we cannot represent the
spill if it is unaligned.
2025-11-11 13:37:21 -08:00
Alex Bradbury
a314b3b401
[MachineCopyPropagation] Remove logic to recognise and delete no-op moves produced after forwarded uses (#167336)
As reported in <https://github.com/llvm/llvm-project/issues/166870>,
some copies with src==reg are not no-ops, e.g. when self-assigning a
w-reg on AArch64 which will zero-extend the corresponding x register.

Revert in order to fix the issue. We may revisit whether the
optimisation can be made safe at a later point.

Reverts dffbc030e75b758e7512518abd499a0f680addbf.
Fixes #166870.
2025-11-11 15:44:54 +00:00
Matt Arsenault
19d472f06e
AArch64: Convert tests to opaque pointers (#167442) 2025-11-11 02:52:45 +00:00
Matt Arsenault
b7ceda3bc9
MachineCombiner: Partially fix losing subregister indexes (#141661)
This fixes verifier errors in this test after earlier passes start
introducing more subregister uses. This probably isn't adequately
tested but I know nothing about this pass.
2025-11-11 02:04:52 +00:00
AZero13
7b12a08f5e
[AArch64] Allow peephole to optimize AND + signed compare with 0 (#153608)
This should be the peephole's job. Because and sets V flag to 0, this is
why signed comparisons with 0 are okay to replace with tst. Note this is
only for AArch64, because ANDS on ARM leaves the V flag the same.

Fixes: https://github.com/llvm/llvm-project/issues/154387
2025-11-10 22:32:31 +00:00
Matt Arsenault
2aa629da6a
AArch64: Enable terminal rule (#165959) 2025-11-10 12:49:21 -08:00
Pranav Kant
2f54efd1bf
[MachineOutliner] Don't outline ADRP pair to avoid incorrect ICF (#160232)
On AArch64, ADRP and its user instructions (LDR, ADD, etc.), that are
referencing a GOT symbol, when separated into different functions by
machine outliner exposes a correctness issue in the linker ICF. In such
cases, user instructions can end up pointing to a folded section (with
its canonical folded symbol), while ADRP instruction point to a GOT
entry corresponding to the original symbol. This leads to loading from
incorrect memory address after ICF. #129122 explains how this can happen
in detail.

This addresses #131660 which should fix two things:
1. Hide the correctness issue described above in the LLVM linker.
2. Allows optimizations that could relax GOT addressing to PC-relative
addressing.
2025-11-10 11:54:16 -08:00
Matt Arsenault
821d2825a4
RuntimeLibcalls: Remove incorrect sincospi from most targets (#166982)
sincospi/sincospif/sincospil does not appear to exist on common
targets. Darwin targets have __sincospi and __sincospif, so define
and use those implementations. I have no idea what version added
those calls, so I'm just guessing it's the same conditions as
__sincos_stret.

Most of this patch is working to preserve codegen when a vector
library is explicitly enabled. This only covers sleef and armpl,
as those are the only cases tested.

The multiple result libcalls have an aberrant process where the
legalizer looks for the scalar type's libcall in RuntimeLibcalls,
and then cross references TargetLibraryInfo to find a matching
vector call. This was unworkable in the sincospi case, since the
common case is there is no scalar call available. To preserve
codegen if the call is available, first try to match a libcall
with the vector type before falling back on the old scalar search.

Eventually all of this logic should be contained in RuntimeLibcalls,
without the link to TargetLibraryInfo. In principle we should perform
the same legalization logic as for an ordinary operation, trying
to find a matching subvector type with a libcall.
2025-11-10 11:05:08 -08:00
Sander de Smalen
7fe60a7685
[AArch64][SVE] Avoid movprfx by reusing register for _UNDEF pseudos. (#166926)
For predicated SVE instructions where we know that the inactive lanes
are undef, it is better to pick a destination register that is not
unique. This avoids introducing a movprfx to copy a unique register to
the destination operand, which would be needed to comply with the tied
operand constraints.

For example:
```
  %src1 = COPY $z1
  %src2 = COPY $z2
  %dst = SDIV_ZPZZ_S_UNDEF %p, %src1, %src2
```
Here it is beneficial to pick $z1 or $z2 as the destination register,
because if it would have chosen a unique register (e.g. $z0) then the
pseudo expand pass would need to insert a MOVPRFX to expand the
operation into:
```
  $z0 = SDIV_ZPZZ_S_UNDEF $p0, $z1, $z2

  ->

  $z0 = MOVPRFX $z1
  $z0 = SDIV_ZPmZ_S $p0, $z0, $z2
```
By picking $z1 directly, we'd get:
```
  $z1 = SDIV_ZPmZ_S, $p0 $z1, $z2
```
2025-11-10 16:33:59 +00:00