451 Commits

Author SHA1 Message Date
Lukacma
d57be195e3
[AArch64] replace SVE intrinsics with no active lanes with zero (#107413)
This patch extends https://github.com/llvm/llvm-project/pull/73964 and
optimises SVE intrinsics into zero constants when predicate is zero.
2024-09-09 10:28:01 +01:00
Jon Roelofs
bded3b3ea9
[llvm][AArch64] Improve the cost model for i128 div's (#107306) 2024-09-05 07:42:23 -07:00
Lukacma
113806d187
[AArch64] optimise SVE cvt intrinsics with no active lanes (#104809)
This patch extends https://github.com/llvm/llvm-project/pull/73964 and
optimises SVE cvt intrinsics away when predicate is zero.
2024-08-29 11:45:14 +01:00
Maciej Gabka
95d2d1cba0
Move stepvector intrinsic out of experimental namespace (#98043)
This patch is moving out stepvector intrinsic from the experimental
namespace.

This intrinsic exists in LLVM for several years now, and is widely used.
2024-08-28 12:48:20 +01:00
cceerczw
67a9093a47
[instCombine][bugfix] Fix crash caused by using of cast in instCombineSVECmpNE (#102472) 2024-08-23 15:30:51 +01:00
Lukacma
29cb1e6b4f
[AArch64] optimise SVE cmp intrinsics with no active lanes (#104779)
This patch extends https://github.com/llvm/llvm-project/pull/73964 and
optimises SVE cmp intrinsics to zero vector when predicate is zero.
2024-08-22 15:51:51 +01:00
David Green
c61d565721
[AArch64] Set scalar fneg to free for fnmul (#104814)
A fneg(fmul(..)) or fmul(fneg(..)) can be folded into a fnmul under
AArch64. https://clang.godbolt.org/z/znPj34Mae

This discounts the cost of the fneg in such patterns to be free.
2024-08-21 18:10:16 +01:00
Lukacma
d7aeea626d
[AArch64] optimise SVE prefetch intrinsics with no active lanes (#103052)
This patch extends https://github.com/llvm/llvm-project/pull/73964 and
optimises away SVE prefetch intrinsics when predicate is zero.
2024-08-15 13:52:35 +01:00
Madhur Amilkanthwar
b73771cf0f
[AArch64] Increase scatter overhead on Neoverse-V2 (#101296)
This patch increases scatter overhead on Neoverse-V2 to 13. This
benefits s128 kernel from TSVC_2 test suite.
SPEC 17, RAJAPerf, and Sptter are unaffected by this patch.

This patch boosts s128 kernel's performance from TSVC test suite by about
40% as this enables vectorization. Also, handle minor code refactoring
for gather related part.
2024-08-14 10:12:40 +05:30
David Green
0b745a1084
[AArch64] Add invalid 1 x vscale costs for reductions and reduction-operations. (#102105)
The code-generator is currently not able to handle scalable vectors of
<vscale x 1 x eltty>. The usual "fix" for this until it is supported is
to mark the costs of loads/stores with an invalid cost, preventing the
vectorizer from vectorizing at those factors. But on rare occasions
loops do not contain load/stores, only reductions.

So whilst this is still unsupported return an invalid cost to avoid
selecting vscale x 1 VFs. The cost of a reduction is not currently used
by the vectorizer so this adds the cost to the add/mul/and/or/xor or
min/max that should feed the reduction. It includes reduction costs
too, for completeness. This change will be removed when code-generation
for these types is sufficiently reliable.

Fixes #99760
2024-08-09 14:25:07 +01:00
Paul Walker
7775a4882d
[LLVM][TTI][SME] Allow optional auto-vectorisation for streaming functions. (#101679)
The command line option enable-scalable-autovec-in-streaming-mode is
used to enable scalable vectors but the same check is missing from
enableScalableVectorization, which is blocking auto-vectorisation.
2024-08-05 11:25:44 +01:00
Sander de Smalen
fb470db7b3
[AArch64] Avoid inlining if ZT0 needs preserving. (#101343)
Inlining may result in different behaviour when the callee clobbers ZT0,
because normally the call-site will have code to preserve ZT0. When
inlining the function this code to preserve ZT0 will no longer be
emitted, and so the resulting behaviour of the program is changed.
2024-08-02 10:29:08 +01:00
David Spickett
d1f3a92ea9 Revert "[AArch64] Remove special-case inserted shuffle cost."
This reverts commit 19b785b7334d01354e8430634bab3c3341c671ca.

My bisect must have been wrong because they're still failing,
and there are follow ups to this that would need unpicking anyway.
2024-07-29 11:24:39 +00:00
David Spickett
19b785b733 Revert "[AArch64] Remove special-case inserted shuffle cost."
This reverts commit f67fa3be4db68afc08c7f3d9523f1533fa5687b7.

Caused test suite failures on AArch64:
https://lab.llvm.org/buildbot/#/builders/17/builds/1349
2024-07-29 11:03:25 +00:00
David Green
6907ab4939 [AArch64] Extend costs for fptoi.sat intrinsics.
Most of these bring the costs in line with the code generation. The f16 costs
without FullFP16 are usually converted to f32. Extended v2f32->v2f64 vectors
similarly use fcvtl + fcvt. As a backup we use the costs similar to the target
independent code, which should give a relatively high cost.
2024-07-28 10:47:40 +01:00
David Green
f67fa3be4d [AArch64] Remove special-case inserted shuffle cost.
This special case tried to measure if the shuffle vector will be multiple
inserts into an existing vector, with one of the lanes already in-place. If so
it reduces the cost by 1 to to represent it will can insert n-1 vector lanes.
This isn't always true though as the original vector may need to be moved to a
new value to start inserting new values into it, if other values from the
original are still needed.

This didn't effect performance much when I tried it, but should hopefully start
to address a regression we see from differences in SLP vectorization lane
orders.
2024-07-25 17:46:48 +01:00
Sander de Smalen
d94ed83a9e [AArch64] Fix assertion failure in getCastInstrCost
We should not call `getVectorElementType` on the result MVT from
`getTypeLegalizationCost` when we don't if the legal type is a
vector. This is the case when the type needs to be legalized
using scalarization.
2024-07-16 10:43:07 +00:00
Graham Hunter
2c0add93b2
[TTI] Return a more sensible cost for histogram intrinsic. (#97397)
This is just an initial cost, making it invalid for any target which
doesn't specifically return a cost for now. Also adds an AArch64
specific cost check.

We will need to improve that later, e.g. by returning a scalarization
cost for generic targets and possibly introducing a new TTI method, at
least once LoopVectorize has changed it's cost model. The reason is
that the histogram intrinsic also effectively contains a gather and
scatter, and we will need details of the addressing to determine an
appropriate cost for that.
2024-07-04 10:59:21 +01:00
Lukacma
9ceb45cc19
[AArch64][SVE] optimisation for unary SVE store intrinsics with no active lanes (#95793)
This patch extends https://github.com/llvm/llvm-project/pull/73964 and
adds optimisation of store SVE intrinsics when predicate is zero.
2024-07-02 11:37:52 +02:00
Nikita Popov
2d209d964a
[IR] Add getDataLayout() helpers to BasicBlock and Instruction (#96902)
This is a helper to avoid writing `getModule()->getDataLayout()`. I
regularly try to use this method only to remember it doesn't exist...

`getModule()->getDataLayout()` is also a common (the most common?)
reason why code has to include the Module.h header.
2024-06-27 16:38:15 +02:00
David Sherwood
2dd4167a09
[LoopVectorize][AArch64] Add limited support for scalable vectorisation of i1 types (#95920)
Previously isElementTypeLegalForScalableVector returned false for i1
types, which also prevented vectorisation of loops with i1 reductions.
This is overkill - we only need to disable vectorisation for loads
and/or stores of i1 types. I've added i1 as a legal type, but changed
the cost model to return an invalid cost for loads and stores.
2024-06-25 15:04:24 +01:00
Sander de Smalen
c436649313
[AArch64] Remove all instances of the 'hasSVEorSME' interfaces. (#96543)
I've not added any new tests for these, because the original conditions
were wrong (they did not consider streaming mode) and we have tests for
the positive cases.
2024-06-25 13:27:06 +01:00
Lukacma
0bd9c49a29
[AArch64][SVE] optimisation for SVE load intrinsics with no active lanes (#95269)
This patch extends #73964 and adds optimisation of load SVE intrinsics
when predicate is zero.
2024-06-25 10:58:16 +02:00
Sander de Smalen
738533c84a
[AArch64] Consider streaming mode in TTI interfaces for vectorization. (#96305)
At the moment, vectorization is only enabled in streaming(-compatible)
mode when enabled through an option. But the interfaces should check
more than just 'hasSVE()', because a function with +sme in streaming
mode should also vectorize with the option enabled.

Additionally, a streaming-compatible function should only be able to use
fixed-length autovec if SVE is available, otherwise the vector code will
be scalarised by the backend.
2024-06-24 11:06:16 +01:00
Graham Hunter
e16f2f5d24
[AArch64] Override isLSRCostLess, take number of instructions into account (#84189)
Adds an AArch64-specific version of isLSRCostLess, changing the relative
importance of the various terms from the formulae being evaluated.

This has been split out from my vscale-aware LSR work, see the RFC for
reference:
https://discourse.llvm.org/t/rfc-vscale-aware-loopstrengthreduce/77131
2024-06-06 14:45:36 +01:00
Graham Hunter
2e8d815596
[TTI] Support scalable offsets in getScalingFactorCost (#88113)
Part of the work to support vscale-relative immediates in LSR.
2024-05-10 11:22:11 +01:00
David Green
363ec6f691 [AArch64][GlobalISel] Common some shuffle mask functions.
This removes the GISel versions of isREVMask, isTRNMask, isUZPMask and
isZipMask. They are combined with the existing versions from SDAG into
AArch64PerfectShuffle.h.
2024-05-06 18:37:04 +01:00
David Sherwood
96b2e35a58
[CostModel][AArch64] Improve fixed-width vector costs for get.active.lane.mask (#89068)
When SVE is available we can lower calls to get.active.lane.mask using
the SVE whilelo instruction, however in practice since vXi1 types are
not legal for NEON we often end up expanding the predicate into a vector
of integers, e.g. v4i1 -> v4i32. This usually happens when we have to
keep the predicate live out of the block, for example when the predicate
is the incoming value to a PHI node in a tail-folded vector loop.
Currently in such cases the intrinsic call has a cost of 1, which is far
too low when considering the extra instructions required to expand the
predicate. This patch fixes that by basing the cost on the number of
lane moves required for expansion. This is required for a follow-on
patch that adds the cost of the intrinsic call to the vectorisation cost
model, so that we can teach the vectoriser to make better choices.
2024-04-24 14:31:06 +01:00
David Green
18bb175428 [AArch64] Add costs for LD3/LD4 shuffles.
Similar to #87934, this adds costs to the shuffles in a canonical LD3/LD4
pattern, which are represented in LLVM as deinterleaving-shuffle(load). This
likely has less effect at the moment than the ST3/ST4 costs as instcombine will
perform certain transforms without considering the cost.
2024-04-21 13:53:22 +01:00
David Green
6c2cc8240e [AArch64] Improve cost of non-zero lane splats
This adds a cost for non-zero lane splats, which is not included by default in
SK_Broadcast but can be handled by aarch64 dup lane instruction.
2024-04-14 12:09:14 +01:00
David Green
a53674359d
[AArch64] Add ZIP and UZP shuffle costs. (#88150)
This adds some costs for the shuffle instructions that should be lowered
to zip1/zip2/uzp1/uzp2 instructions.
2024-04-11 08:45:28 +01:00
David Green
f0e79d9152 [AArch64] Add a cost for identity shuffles.
These are mostly handled at a higher level when costing shuffles, but some
masks can end up being identity or concat masks which we can treat as free.
2024-04-09 17:16:14 +01:00
David Green
4ac2721e51
[AArch64] Add costs for ST3 and ST4 instructions, modelled as store(shuffle). (#87934)
This tries to add some costs for the shuffle in a ST3/ST4 instruction,
which are represented in LLVM IR as store(interleaving shuffle). In
order to detect the store, it needs to add a CxtI context instruction to
check the users of the shuffle. LD3 and LD4 are added, LD2 should be a
zip1 shuffle, which will be added in another patch.

It should help fix some of the regressions from #87510.
2024-04-09 16:36:08 +01:00
Il-Capitano
308ed0233a
[Intrinsics] Make patchpoint.i64 generic on its return type (#85911)
Currently patchpoints can only have two result types, `void` and `i64`.
This limits the result to general purpose registers.
This patch makes `patchpoint.i64` an overloadable intrinsic, allowing
result values that can fit in a single register (e.g. integers,
pointers, floats).
2024-03-26 19:08:52 +05:30
Jeremy Morse
b9d83eff25
[NFC][RemoveDIs] Use iterators for insertion at various call-sites (#84736)
These are the last remaining "trivial" changes to passes that use
Instruction pointers for insertion. All of this should be NFC, it's just
changing the spelling of how we identify a position.

In one or two locations, I'm also switching uses of getNextNode etc to
using std::next with iterators. This too should be NFC.

---------

Merged by: Stephen Tozer <stephen.tozer@sony.com>
2024-03-19 16:36:29 +00:00
Graham Hunter
56abb8d535 [AArch64] Be stricter about insert/extract index
Post-commit fixup patch for a request on
https://github.com/llvm/llvm-project/pull/81135
2024-03-05 09:50:32 +00:00
Graham Hunter
03f852f704
[AArch64] Improve cost model for legal subvec insert/extract (#81135)
Currently we model subvector inserts and extracts as shuffles,
potentially going as far as scalarizing. If the types are legal then
they can just be simple zip/unzip operations, or possible even no-ops.
Change the cost to a relatively small one to ensure that simple loops
featuring such operations between fixed and scalable vector types that
are effectively the same at a given sve width can be unrolled and
further optimized.
2024-03-04 16:17:01 +00:00
Paschalis Mpeis
bbdc62e718
[AArch64][CostModel] Improve scalar frem cost (#80423)
In AArch64 the cost of scalar frem is the cost of a call to 'fmod'.
2024-02-23 09:29:45 +00:00
Usman Nadeem
267d6b5ed2
[AArch64][SVE] Instcombine uzp1/reinterpret svbool to use vector.insert (#81069)
Concatenating two predictes using uzp1 after converting to double length
using sve.convert.to/from.svbool is optimized poorly in the backend,
resulting in additional `and` instructions to zero the lanes. See
https://github.com/llvm/llvm-project/pull/78623/

Combine this pattern to use `llvm.vector.insert` to concatenate and get
rid of convert to/from svbools.
2024-02-15 10:40:09 -08:00
Alexey Bataev
7bc079c852
[TTI]Fallback to SingleSrcPermute shuffle kind, if no direct estimation for
extract subvector.

Many targets do not have cost for extractsubvector shuffle kind, but
have the costs for single source permute. If there are no costs
estimation for extractsubvector, better to switchto single source
permute for better cost estimation.

Reviewers: RKSimon, davemgreen, arsenm

Reviewed By: RKSimon

Pull Request: https://github.com/llvm/llvm-project/pull/79837
2024-02-12 07:09:49 -05:00
Sander de Smalen
d313614b60
[AArch64] Replace LLVM IR function attributes for PSTATE.ZA. (#79166)
Since https://github.com/ARM-software/acle/pull/276 the ACLE
defines attributes to better describe the use of a given SME state.

Previously the attributes merely described the possibility of it being
'shared' or 'preserved', whereas the new attributes have more semantics
and also describe how the data flows through the program.

For ZT0 we already had to add new LLVM IR attributes:
* aarch64_new_zt0
* aarch64_in_zt0
* aarch64_out_zt0
* aarch64_inout_zt0
* aarch64_preserves_zt0

We have now done the same for ZA, such that we add:
* aarch64_new_za       (previously `aarch64_pstate_za_new`)
* aarch64_in_za (more specific variation of `aarch64_pstate_za_shared`)
* aarch64_out_za (more specific variation of `aarch64_pstate_za_shared`)
* aarch64_inout_za (more specific variation of
`aarch64_pstate_za_shared`)
* aarch64_preserves_za (previously `aarch64_pstate_za_shared,
aarch64_pstate_za_preserved`)

This explicitly removes 'pstate' from the name, because with SME2 and
the new ACLE attributes there is a difference between "sharing ZA"
(sharing
the ZA matrix register with the caller) and "sharing PSTATE.ZA" (sharing
either the ZA or ZT0 register, both part of PSTATE.ZA with the caller).
2024-02-01 13:37:37 +00:00
Sander de Smalen
3abf55a68c
[AArch64][SME] Fix inlining bug introduced in #78703 (#79994)
Calling a `__arm_locally_streaming` function from a function that
is not a streaming-SVE function would lead to incorrect inlining.

The issue didn't surface because the tests were not testing what
they were supposed to test.
2024-01-31 11:38:29 +00:00
David Green
a2d68b4bec
[SelectOpt] Add handling for Select-like operations. (#77284)
Some operations behave like selects. For example `or(zext(c), y)` is the
same as select(c, y|1, y)` and instcombine can canonicalize the select
to the or form. These operations can still be worthwhile converting to
branch as opposed to keeping as a select or or instruction.

This patch attempts to add some basic handling for them, creating a
SelectLike abstraction in the select optimization pass. The backend can
opt into handling `or(zext(c),x)` as a select if it could be profitable,
and the select optimization pass attempts to handle them in much the
same way as a `select(c, x|1, x)`. The Or(x, 1) may need to be added as
a new instruction, generated as the or is converted to branches.

This helps fix a regression from selects being converted to or's
recently.
2024-01-22 23:46:58 +00:00
Sander de Smalen
5f41cef58f
[AArch64] NFC: Simplify discombobulating 'requiresSMChange' interface (#78703)
Having it return a `std::optional<bool>` is unnecessarily confusing.
This patch changes it to a simple 'bool'.

This patch also removes the 'BodyOverridesInterface' operand because
there is only a single use for this which is easily rewritten.
2024-01-19 16:15:38 +00:00
Florian Hahn
e473daa779
[AArch64] Improve cost computations for odd vector mem ops. (#78181)
Improve cost computaton for odd vector mem ops by breaking them down
into smaller power-of-2 parts and sum up the cost of those parts.

This fixes the current cost estimates, which for most parts
underestimated the cos, due to using getTypeLegalizationCost, which
widens to the next power-of-2 in a single step in most cases. This
doesn't reflect the actual cost.

See https://llvm.godbolt.org/z/vMsnxMf1v for codegen for the tests.

Note that there is a special case for v3i8, for which current codegen is
pretty bad, due to automatic widening to v4i8, which in turn requires
the conversion to go through memory ops in the stack. I am planning on
fixing that as a follow-up, but I am not yet sure where to best fix
this.

At the moment, there are almost no cases in which such vector operations
will be generated automatically. The motivating case is non-power-of-2
SLP vectorization: https://github.com/llvm/llvm-project/pull/77790

PR: https://github.com/llvm/llvm-project/pull/78181
2024-01-17 21:32:06 +00:00
Mark Harley
adfd13157d
[AArch64][SVE] Add optimisation for SVE intrinsics with no active lanes (#73964)
This patch introduces optimisations for SVE intrinsic function calls
which have all false predicates.
2024-01-10 11:56:52 +00:00
Sander de Smalen
81b7f115fb
[llvm][TypeSize] Fix addition/subtraction in TypeSize. (#72979)
It seems TypeSize is currently broken in the sense that:

  TypeSize::Fixed(4) + TypeSize::Scalable(4) => TypeSize::Fixed(8)

without failing its assert that explicitly tests for this case:

  assert(LHS.Scalable == RHS.Scalable && ...);

The reason this fails is that `Scalable` is a static method of class
TypeSize,
and LHS and RHS are both objects of class TypeSize. So this is
evaluating
if the pointer to the function Scalable == the pointer to the function
Scalable,
which is always true because LHS and RHS have the same class.

This patch fixes the issue by renaming `TypeSize::Scalable` ->
`TypeSize::getScalable`, as well as `TypeSize::Fixed` to
`TypeSize::getFixed`,
so that it no longer clashes with the variable in
FixedOrScalableQuantity.

The new methods now also better match the coding standard, which
specifies that:
* Variable names should be nouns (as they represent state)
* Function names should be verb phrases (as they represent actions)
2023-11-22 08:52:53 +00:00
Sander de Smalen
00a831421f
[AArch64][SME] Extend Inliner cost-model with custom penalty for calls. (#68416)
This is a stacked PR following on from #68415 

This patch has two purposes:
(1) It tries to make inlining more likely when it can avoid a
streaming-mode change.
(2) It avoids inlining when inlining causes more streaming-mode changes.

An example of (1) is:
```
  void streaming_compatible_bar(void);

  void foo(void) __arm_streaming {
    /* other code */
    streaming_compatible_bar();
    /* other code */
  }

  void f(void) {
    foo();            // expensive streaming mode change
  }

  ->

  void f(void) {
    /* other code */
    streaming_compatible_bar();
    /* other code */
  }
```
where it wouldn't have inlined the function when foo would be a
non-streaming function.

An example of (2) is:
```
  void streaming_bar(void) __arm_streaming;

  void foo(void) __arm_streaming {
    streaming_bar();
    streaming_bar();
  }

  void f(void) {
    foo();            // expensive streaming mode change
  }

  -> (do not inline into)

  void f(void) {
    streaming_bar();  // these are now two expensive streaming mode changes
    streaming_bar();
  }```
2023-10-31 10:28:40 +00:00
Igor Kirillov
849f963e31
[CodeGen] Improve ExpandMemCmp for more efficient non-register aligned sizes handling (#70469)
* Enhanced the logic of ExpandMemCmp pass to merge contiguous
subsequences
  in LoadSequence, based on sizes allowed in `AllowedTailExpansions`.
* This enhancement seeks to minimize the number of basic blocks and
produce
  optimized code when using memcmp with non-register aligned sizes.
* Enable this feature for AArch64 with memcmp sizes modulo 8 equal to
  3, 5, and 6.

Reapplication of #69942 after fixing a bug
2023-10-30 18:40:48 +00:00
Sander de Smalen
6d30bc0085
[AArch64][SME] Allow inlining when streaming-mode attributes dont match up. (#68415)
The use-case here is to support things like:

  int foo(int x, int y) __arm_streaming { return std::max<int>(x, y); }

where the call to non-streaming `std::max<int>(x, y)` can be safely
inlined into the streaming function.

This is a first step and will need further work to allow more cases
(e.g. more finegrained analysis of the function calls to ensure they
don't result in any incompatible instructions for the requested mode).
2023-10-30 10:47:07 +00:00