892 Commits

Author SHA1 Message Date
Florian Hahn
89ae085859
[VPlan] Remove VPVectorPointer for part 0 after unrolling. (#149735)
VPVectorPointer for part 0 is just the pointer operand. Simplify it
after unrolling. This removes a large number of redundant GEPs with
index 0.

PR: https://github.com/llvm/llvm-project/pull/149735
2025-07-27 13:53:26 +01:00
Florian Hahn
80c43b6c07
[VPlan] Add ExtractLane VPInst to extract across multiple parts. (#148817)
This patch adds a new ExtractLane VPInstruction which extracts across
multiple parts using a wide index, to be used in combination with
FirstActiveLane.

The patch updates early-exit codegen to use it instead ExtractElement,
which is only per-part. With this change, interleaving should work
correctly with early-exit loops.

The patch removes the restrictions added in 6f43754e9 (#145877), but
does not yet automatically select interleave counts > 1 for early-exit
loops.

I'll share a patch as follow-up. The cost of extracting a lane adds
non-trivial overhead in the exit block, so that should be considered
when picking the interleave count.

PR: https://github.com/llvm/llvm-project/pull/148817
2025-07-27 08:08:25 +01:00
Florian Hahn
fa3ec0c17c
[VPlan] Materialize constant vector trip counts before final opts. (#142309)
Materialize constant vector trip counts before ::execute, if the trip
count can be computed as Original (TC / (VF * UF)) * (VF * UF). For now
this excludes when the tail is folded or scalar epilogues are required.

This enables removing a number of redundant branches from the middle
block.

For now this is also only done when not vectorizing the epilogue, as the
simplification complicates stitching the 2 plans together.

PR: https://github.com/llvm/llvm-project/pull/142309
2025-07-26 17:16:36 +01:00
Florian Hahn
e5f5813042
[LV] Update some tests to have variable trip counts. (NFC)
Update tests for which checking both the scalar resume and exit values
is interesting, because they have first-order recurrences to have
variable trip-counts, to avoid the branch in the middle.block being
folded away by https://github.com/llvm/llvm-project/pull/142309.

For similar reasons, also update check-prof-info.ll
2025-07-26 09:59:06 +01:00
Florian Hahn
9a201531ed
[LV] Bail out early if runtime checks are known to fail.
There are a number of cases for which SCEV may not be able to prove a
predicate will always be true/false, which may be simplified to a
constant during expansion (see discussion in
https://github.com/llvm/llvm-project/pull/131538).

Bail out early if runtime checks are known to always fail, as the
vector loop generated later will never execute.
2025-07-26 09:26:15 +01:00
Florian Hahn
77b1b956da
[LV] Also clamp MaxVF by trip count when maximizing vector bandwidth. (#149794)
Also clamp the max VF when maximizing vector bandwidth by the maximum
trip count. Otherwise we may end up choosing a VF for which the vector
loop never executes.

PR: https://github.com/llvm/llvm-project/pull/149794
2025-07-23 10:19:56 +01:00
Florian Hahn
37f0f10a85
[LV] Don't vectorize epilogue with scalable VF if no iterations remain. (#149789)
Currently we may try to vectorize the epilogue with a scalable VF, even
if there are no remaining iterations after the main vector loop with a
fixed VF.

Update selectEpilogueVectorizationFactor to always compute the number of
remaining iterations and exit early if no epilogue iterations remain.

Fixes https://github.com/llvm/llvm-project/issues/149726

PR: https://github.com/llvm/llvm-project/pull/149789
2025-07-22 13:13:31 +01:00
Florian Hahn
3fd53db858
[VPlan] Remove unneeded VPVectorPointer after narrowing to replicate.
The replicate recipes created when narrowing interleave groups don't
need a VPVectorPointer, they can simply use the existing pointer.
2025-07-19 20:18:04 +01:00
Florian Hahn
004c67ea25
[LV] Vectorize maxnum/minnum w/o fast-math flags. (#148239)
Update LV to vectorize maxnum/minnum reductions without fast-math flags,
by adding an extra check in the loop if any inputs to maxnum/minnum are
NaN, due to maxnum/minnum behavior w.r.t to signaling NaNs. Signed-zeros 
are already handled consistently by maxnum/minnum.

If any input is NaN,
 *exit the vector loop,
 *compute the reduction result up to the vector iteration that contained
   NaN inputs and
 * resume in the scalar loop


New recurrence kinds are added for reductions using maxnum/minnum
without fast-math flags.

PR: https://github.com/llvm/llvm-project/pull/148239
2025-07-18 21:58:19 +01:00
Nicholas Guy
b5e3fffd20
[LoopVectorizer][NFC] Require asserts on maxbandwidth-regpressure.ll (#149484)
Fix for buildbot failure:
https://lab.llvm.org/buildbot/#/builders/11/builds/19837
2025-07-18 10:21:21 +01:00
Nicholas Guy
20fc297ce3
[LoopVectorizer] Only check register pressure for VFs that have been enabled via maxBandwidth (#149056)
Currently if MaxBandwidth is enabled, the register pressure is checked
for each VF. This changes that to only perform said check if the VF
would not have otherwise been considered by the LoopVectorizer if
maxBandwidth was not enabled.

Theoretically this allows for higher VFs to be considered than would
otherwise be deemed "safe" (from a regpressure perspective), but more
concretely this reduces the amount of work done at compile-time when
maxBandwidth is enabled.
2025-07-18 09:21:20 +01:00
Florian Hahn
afe8150780
[VPlan] Simplify exituser handling by generating all extracts first(NFCI)
Simplify the handling of exit users by generating all extracts first
(safe option), and have FOR handling optimize the extracts, similar to
already done for reductions and inductions.

NFC modulo first-order recurrence extract order in middle block.
2025-07-16 08:14:12 +01:00
Florian Hahn
cfdd5ca2ed
[LV] Add tests for fmin reductions without fast-math flags.
Some of those reductions can be vectorized with extra checks.

Extra tests for https://github.com/llvm/llvm-project/pull/148239 and
follow-ups.
2025-07-15 13:34:12 +01:00
David Sherwood
c363a3f9c8
[LV] Ensure getScaledReductions only matches extends inside the loop (#148264)
In getScaledReductions for the case where we try to match a partial
reduction of the form:

%phi = phi i32 ...
...
%add = add i32 %phi, %zext

where

%zext = i8 %some_val to i32

we should ensure that %zext is actually inside the loop.

Fixes https://github.com/llvm/llvm-project/issues/148260
2025-07-15 09:54:58 +01:00
Luke Lau
c8d0e24745
[VPlan] Preserve trunc nuw/nsw in VPRecipeWithIRFlags (#144700)
This preserves the nuw/nsw flags on widened truncs by checking for
TruncInst in the VPIRFlags constructor

The motivation for this is to be able to fold away some redundant truncs
feeding into uitofps (or potentially narrow the inductions feeding them)
2025-07-15 15:34:14 +08:00
Florian Hahn
f4c7cc26b6
[LV] Use more precise isPredicatedInst in legacy CCH (NFC).
Legal::isMaskRequired may be overly conservative and also return true
when no mask is actually required.

Use isPredicatedInst from the cost model instead, which fixes a
cost-model divergence between legacy and VPlan cost model where the
legacy cost model incorrectly assumed some loads were predicated.

Fixes https://github.com/llvm/llvm-project/issues/148431.
2025-07-13 19:55:34 +01:00
Florian Hahn
cc65da0fb1
[LV] Update fmax tests to include ogt/olt/ole/ugt predicates.
Adjust and update tests as per feedback in
https://github.com/llvm/llvm-project/pull/146711.
2025-07-13 12:16:54 +01:00
David Sherwood
74e3dfe389
[LV] Disable forcing interleaving for uncountable early exit loops (#147993)
Interleaving does not currently work properly when vectorising loops
with uncountable early exits. Interleaving is already disabled for
normal vectorisation and for the pragma/hint - this patch also disables
it when using -force-vector-interleave.
2025-07-11 09:46:21 +01:00
Florian Hahn
c452de1715
Reapply "[VPlan] Allow derived IVs and scalar-steps in narrowing interleave."
This reverts commit f5ed863176dd286462cd5558723dfe445967fedf.

Recommit patch now that the crash exposed by the change has been fixed.
2025-07-10 20:48:19 +01:00
Florian Hahn
253f8b6873
[VPlan] Support single-scalar VPReplicateRecipes when narrowing IGs.
When narrowing interleave groups, we can treat single scalar
VPReplicateRecipes as already narrowed.
2025-07-09 21:30:44 +01:00
Florian Hahn
1f3f9874b0
[VPlan] Fix crash when narrowing interleave-groups with reuse.
If a wide load is used multiple times in an expression, it will be
narrowed the first time. Re-use the already narrowed op in that case to
fix crash.
2025-07-04 21:32:24 +01:00
Florian Hahn
6efa3dfb7b
[VPlan] Handle interleave groups with trivially narrow operands.
If all operands to an interleave group are already trivially narrow,
narrow the interleave group itself as well.
2025-07-03 21:02:10 +01:00
Florian Hahn
08ed9e17bf
[LV] Add tests for narrowing interleave groups with single scalar ops.
Add test coverage for narrowing interleave groups with constants and
uniform loads.
2025-07-03 20:32:11 +01:00
David Sherwood
f575b18fdc
[LV] Add support for partial reductions without a binary op (#133922)
Consider IR such as this:

for.body:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
  %accum = phi i32 [ 0, %entry ], [ %add, %for.body ]
  %gep.a = getelementptr i8, ptr %a, i64 %iv
  %load.a = load i8, ptr %gep.a, align 1
  %ext.a = zext i8 %load.a to i32
  %add = add i32 %ext.a, %accum
  %iv.next = add i64 %iv, 1
  %exitcond.not = icmp eq i64 %iv.next, 1025
  br i1 %exitcond.not, label %for.exit, label %for.body

Conceptually we can vectorise this using partial reductions too,
although the current loop vectoriser implementation requires the
accumulation of a multiply. For AArch64 this is easily done with
a udot or sdot with an identity operand, i.e. a vector of (i16 1).

In order to do this I had to teach getScaledReductions that the
accumulated value may come from a unary op, hence there is only
one extension to consider. Similarly, I updated the vplan and
AArch64 TTI cost model to understand the possible unary op.

---------

Co-authored-by: Matt Devereau <matthew.devereau@arm.com>
2025-07-02 13:05:51 +01:00
Mel Chen
bc8dad1c7e
[VPlan] Emit VPVectorEndPointerRecipe for reverse interleave pointer adjustment (#144864)
A reverse interleave access is essentially composed of multiple
load/store operations with same negative stride, and their addresses are
based on the last lane address of member 0 in the interleaved group.

Currently, we already have VPVectorEndPointerRecipe for computing the
last lane address of consecutive reverse memory accesses. This patch
extends VPVectorEndPointerRecipe to support constant stride and extracts
the reverse interleave group address adjustment from
VPInterleaveRecipe::execute, replacing it with a
VPVectorEndPointerRecipe.

The final goal is to support interleaved accesses with EVL tail folding.
Given that VPInterleaveRecipe is large and tightly coupled — combining
both load and store, and embedding operations like reverse pointer
adjustion (GEP), widen load/store, deinterleave/interleave, and reversal
— breaking it down into smaller, dedicated recipes may allow
VPlanTransforms::tryAddExplicitVectorLength to lower them into EVL-aware
form more effectively.

One foreseeable challenge is that
VPlanTransforms::convertToConcreteRecipes currently runs after
tryAddExplicitVectorLength, so decomposing VPInterleaveRecipe will
likely need to happen earlier in the pipeline to be effective.
2025-07-02 18:16:02 +08:00
David Sherwood
9b13dfdfbc
[LV] Use vscale for tuning to improve branch weight estimates (#144733)
In addBranchWeightToMiddleTerminator we attempt to add branch weights to
the middle block terminator. We pessimistically assume vscale=1, whereas
we can improve the estimate by using the value of vscale used for
tuning.
2025-07-01 13:23:38 +01:00
Florian Hahn
b822a32659
[VPlan] Fix crash when trying to narrow interleave group storing const.
Use dyn_cast_null to handle the case where an interleave groups stores a
constant in any of its lanes.
2025-06-29 21:29:12 +01:00
Florian Hahn
f5ed863176
Revert "[VPlan] Allow derived IVs and scalar-steps in narrowing interleave."
This reverts commit 2787759ef2e41b19f8bfde06fe9a26b25d1f5834.

This exposed a crash on some build bots. Revert to investigate.
2025-06-29 14:40:03 +01:00
Florian Hahn
2787759ef2
[VPlan] Allow derived IVs and scalar-steps in narrowing interleave.
Both VPDerivedIVRecipe and VPScalarIVSteps recipe should be supported in
narrowInterleaveGroups:
 * VPDerivedIVRecipe is based on the canonical IV and independent of VF,
 * VPScalarIVSteps takes the VF as operand, so it will be updated by
   narrowInterleaveGroup.
2025-06-29 13:18:51 +01:00
Florian Hahn
1949536494
[VPlan] Also visit VPBBs outside loop region when unrolling by VF.
Make sure all VPBBs outside the top-level loop region and directly
inside the region are visited; all those blocks may contain
VPReplicateRecipes that need unrolling.

This makes sure we unroll VPRepicateRecipes by VF if they are hoisted
out of the loop, but cannot be converted to single scalar recipes yet.
2025-06-28 19:02:22 +01:00
Florian Hahn
526701f8dc
[LV] Add additional tests for narrowing interleave groups.
Add additional test coverage for narrowing interleave groups with
derived IVs & scalar steps.
2025-06-27 21:18:14 +01:00
David Sherwood
bf2b14acf3
[LV] Enable auto-vectorisation of loops with uncountable exits (#133099)
Until now the feature to enable vectorisation of some early exit
loops with uncountable exits was controlled under a flag, off by
default. Now that we have efficient code generation for
vectorising such loops (see PR #130766) and we still have some
time from the next LLVM release it seems like a good time point
to enable the feature by default. If any issues arise post-commit
it can be easily reverted.

Using this patch I built and ran the LLVM test suite successfully,
which on neoverse-v1 led to the vectorisation of 114 additional
early exit loops. I also built and ran SPEC2017 successfully for
both neoverse-v1 and neoverse-v2.
2025-06-27 10:39:33 +01:00
Florian Hahn
ec62dee703
[VPlan] Handle FirstActiveLane when unrolling. (#145394)
Currently FirstActiveLane is not handled correctly during
 unrolling. This is currently causing mis-compiles when
 vectorizing early-exit loops with interleaving forced.

This patch updates handling of FirstActiveLane to be analogous to
computing final reduction results: during unrolling, the created copies
for its original operand are added as additional operands, and
FirstActiveLane will always produce the index of the first active lane
across all unrolled iterations.

Note that some of the generated code is still incorrect, as we also need
to handle ExtractElement with FirstActiveLane operands. I will share
patches for those soon as well.

PR: https://github.com/llvm/llvm-project/pull/145394
2025-06-27 08:44:57 +01:00
Florian Hahn
5b76cdba5a
[VPlan] Handle AnyOf when unrolling. (#145340)
Currently AnyOf is not handled correctly during unrolling. This is
currently causing mis-compiles when vectorizing early-exit loops with
interleaving forced (even though selectInterleaveCount will currently
only pick IC = 1, unless forced by the user).

This patch updates handling of AnyOf to be analogous to computing final
reduction results: during unrolling, the created copies for its original
operand are added as additional operands, and AnyOf will always produce
the reduced value across all unrolled iterations.

Note that the generated code is still incorrect, as we also need to
handle FirstActiveLane and ExtractElement with FirstActiveLane operands.
I will share patches for those soon as well.

PR: https://github.com/llvm/llvm-project/pull/145340
2025-06-26 14:19:38 +01:00
Florian Hahn
830b2c842e
[LV] Replace redundant ExtractLastElement of reduction result (NFC).
Replace redundant ExtractLastElement VPInstructions early. This is NFC,
as the VPInstruction computing the final result is vector-to-scalar,
producing a single scalar already. This enables follow-up changes to
model more aspects of reductions directly in VPlan.
2025-06-24 21:48:58 +01:00
Florian Hahn
b054363645
[LV] Add tests showing incorrect vector interleaving with early exits.
When interleaving is forced for early-exit loops, we currently create
incorrect code.

Test coverage for scalable vectors is added as AArch64 specific test.
2025-06-23 16:24:13 +01:00
Florian Hahn
f9c9a32e9c
[LV] Add tests with fmax reductions without fast-math flags.
Adds extra tests with fmax reductions without fast-math flags for
upcoming patches.
2025-06-22 20:35:38 +01:00
Florian Hahn
58b939abe5
[VPlan] Support matching constants in narrowInterleaveGroups.
Matching constants can trivially be broadcasted, allow them if the same
constant is used for all recipes in a bundle.
2025-06-22 08:45:40 +01:00
Florian Hahn
c455f4a32d
[LV] Add more tests for narrowing interleave groups with live-ins. 2025-06-21 22:03:19 +01:00
Philip Reames
c103bbc836
[LV] Consider whether vscale is a known power of two for iteration check (#144963)
Going mostly by the comment here - but it says "vscale is not
necessarily a power-of-2". Both in tree targets have vscale as a power
of two, and we have an existing TTI hook for that.
2025-06-20 11:37:27 -07:00
Florian Hahn
e8be733a3c
[VPlan] Remove redundant ExtractLastElement from vector-to-scalar VPI.
Recipes that are vector-to-scalar are guaranteed to generate a scalar
value, so the extract is redundant after VPlan unrolling. Remove it.

This removes unneeded ExtractLastElement VPInstruction of reduction
result computations.
2025-06-20 12:45:20 +01:00
Florian Hahn
c4c2d777f4
[VPlan] Fix handling of ReductionStartVector for rdxs when unrolling.
Update handling of ReductionStartVector in VPlanUnroll for partial
reductions. The new code makes sure all parts are properly set to the
cloned ReductionStartVector.

Fixes a mis-compile reported for
https://github.com/llvm/llvm-project/pull/142290.
2025-06-19 13:26:19 +01:00
Paul Walker
e478a22d54
[LLVM][IRBuilder] Use NUW arithmetic for Create{ElementCount,TypeSize}. (#143532)
This put the onus on the caller to ensure the result type is big enough.
In the unlikely event a cropped result is required then explicitly
truncate a safe value.
2025-06-19 13:24:39 +01:00
Florian Hahn
046e2f545e
[LV] Add interleaving test with partial reductions and non-const start.
Add test coverage for mis-compile after
https://github.com/llvm/llvm-project/pull/142290.
2025-06-19 12:55:16 +01:00
Luke Lau
9dd1c66e8f
[VPlan] Expand VPWidenIntOrFpInductionRecipe into separate recipes (#118638)
The motivation of this PR is to make #115274 easier to implement, and
should allow us to add EVL support by just passing EVL to the VF
operand.

The current difficulty with widening IVs with EVL is that
VPWidenIntOrFpInductionRecipe generates its own backedge value. Since
it's a VPHeaderPHIRecipe the VF operand must be in the preheader, which
means we can't use the EVL since it's defined in the loop body.

The gist in this PR is to take the approach in #114305 and expand
VPWidenIntOrFpInductionRecipe into several recipes for the initial
value, phi and backedge value just before execution. I.e. this example:

```
  vector.ph:
  Successor(s): vector loop

  <x1> vector loop: {
    vector.body:
      WIDEN-INDUCTION %i = phi %start, %step, %vf
      ...
      EMIT branch-on-count ...
    No successors
  }
```

gets expanded to:

``` 
vector.ph:
  ...
  vp<%induction.start> = ...
  vp<%induction.increment> = ...

Successor(s): vector loop

<x1> vector loop: {
  vector.body:
    ir<%i> = WIDEN-PHI vp<%induction.start>, vp<%vec.ind.next>
    ...
    vp<%vec.ind.next> = add ir<%i>, vp<%induction.increment>
    EMIT branch-on-count ...
  No successors
}
```

This allows us to a value defined in the loop in the backedge value, and
also means we can just reuse the existing backedge fixups in
VPlan::execute without having to specially handle it ourselves.

After this #115274 should just become a matter of setting the VF operand
to EVL (and building the increment step in the loop body, not the
preheader).
2025-06-17 18:24:07 +01:00
Mary Kassayova
c377ce1216
[AArch64][VecLib] Add libmvec support for AArch64 targets (#143696)
This patch adds support for the `libmvec` vector library on AArch64
targets. Currently, all `libmvec` functions in GLIBC version 2.40 are
supported. The full list of math functions enabled can be found
[here](96abd59bf2/sysdeps/aarch64/fpu/Versions)
(up to GLIBC 2.40).

Previously, `libmvec` was only supported on x86_64 targets. Attempts to
use it on AArch64 resulted in the following error from Clang:
`unsupported option 'libmvec' for target 'aarch64'`.
2025-06-17 11:07:43 +01:00
Florian Hahn
d3bc834ece
[LV] Update check to find epilogue resume value to check all incoming.
This fixes a crash where all incoming values for the epilogue resume
value are zero, because there are no remaining iterations to execute for
the epilogue loop.
2025-06-16 21:10:12 +01:00
David Sherwood
a75e0627f9
[LV] Use vscale for tuning when updating profile information (#143690)
In fixVectorizedLoop we call setProfileInfoAfterUnrolling to update the
profile information after vectorising, however for scalable VFs we
pessimistically assume vscale=1. We can improve upon this by using the
value of vscale used for tuning, i.e. when targeting neoverse-v1 the
expected value is 2.
2025-06-16 10:02:38 +01:00
Florian Hahn
790df93298
[VPlan] Mark VPFirstOrderRecurrencePHI as not reading/writing memory.
First-order recurrence phis don't have side-effects and don't read or
write memory. Mark them as such.
2025-06-15 22:00:47 +01:00
Florian Hahn
087a6ac420
[LV] Add users to some first-order recurrence tests.
Add extra users to ensure the recurrence cannot be DCE'd.

Also re-generates some checks.
2025-06-15 21:24:10 +01:00