6216 Commits

Author SHA1 Message Date
Alexey Bataev
ac4a38e9bd
[SLP] Emit reduction instead of 2 extracts + scalar op, when vectorizing operands (#147583)
Added emission of the 2-element reduction instead of 2 extracts + scalar
op, when trying to vectorize operands of the instruction, if it is more
profitable.
2025-07-09 19:52:09 -04: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
Ramkumar Ramachandra
62f8377e40
[LV] Extend FindFirstIV to unsigned case (#146386)
Extend FindFirstIV vectorization to the unsigned case by introducing and
handling FindFirstIVUMin.

Co-authored-by: Florian Hahn <flo@fhahn.com>
2025-07-09 15:56:40 +01:00
Alexey Bataev
9e132f5068 [SLP][NFC]Move function SLPVectorizerPass::tryToVectorize around, NFC 2025-07-09 05:34:36 -07:00
Florian Hahn
64686c59c3
[VPlan] Connect (MemRuntime|SCEV)Check blocks as VPlan transform (NFC). (#143879)
Connect SCEV and memory runtime check block directly in VPlan as
VPIRBasicBlocks, removing ILV::emitSCEVChecks and
ILV::emitMemRuntimeChecks.

The new logic is currently split across
LoopVectorizationPlanner::addRuntimeChecks which collects a list of
{Condition, CheckBlock} pairs and performs some checks and emits remarks
if needed. The list of checks is then added to VPlan in
VPlanTransforms::connectCheckBlocks.

PR: https://github.com/llvm/llvm-project/pull/143879
2025-07-09 14:03:25 +02:00
Gaëtan Bossu
50facad7fc
[SLP][REVEC] Fix insertelement legality checks (#146921)
The current code assumes that all the values in VL are valid
instructions, while it is possible to get poison.
2025-07-09 10:28:50 +01:00
James Y Knight
093afed969
[VPlan] Fix miscompile after PR #142433. (#147398)
This fixes a bug introduced by aa2402931908317f5cc19b164ef17c5a74f2ae67,
"[VPlan] Unroll VPReplicateRecipe by VF", which cloned a
VPReplicateRecipe without transferring the flags from the original.

That can cause incorrect nsw/nuw flags to be emitted on the new
instructions, which may result in miscompiles.

It turns out there were no test-cases in the repo which end up hitting
the situation where the recipe requires instruction clones to have
different flags from the underlying instruction. The existing tests
covered the flags being correct when the replacement instruction is a
vectorized version of the initial instruction, but not when it required
clones. A new test is added covering this.
2025-07-08 14:51:27 -04:00
Ramkumar Ramachandra
f1451e9f07
[LV] Improve code using drop_{begin,end} (NFC) (#147504) 2025-07-08 13:42:10 +01:00
Ramkumar Ramachandra
f1e1b48023
[LV] Strip redundant fn in VPBuilder (NFC) (#147499) 2025-07-08 13:41:29 +01:00
Luke Lau
2e5776130b
[VPlan] Simplify select !c, x, y -> select c, y, x (#147268)
This is split off from #133993

On its own this simplification isn't that useful, but it allows us to
make the equivalent VPBlendRecipe optimisation more generic by operating
on VPInstructions.

In order to actually test this without #133993, I've had to also extend
the m_Not pattern matcher to also catch VPWidenRecipes, since I couldn't
really think of a straightforward way to create a VPInstruction::Select
with a negated condition.
2025-07-08 15:56:04 +08:00
Florian Hahn
1113224f94
[VectorCombine] Account for IRBuilder simplification in translateExt.
After https://github.com/llvm/llvm-project/pull/146350,
CreateExtractElement may return a folded value and not create an
ExtractElement instruction.

Replace cast with dyn_cast. Note that the function returns nullptr
already earlier if the extract may be constant folded.

Fixes https://github.com/llvm/llvm-project/issues/147218
2025-07-07 13:39:39 +02:00
Florian Hahn
6a9a16da7a
[VPlan] Replace RdxDesc with RecurKind in VPReductionPHIRecipe (NFC). (#142322)
Replace RdxDesc with RecurKind in VPReductionPHIRecipe, as
all VPlan analyses and codegen only require the recurrence kind. This
enables creating new VPReductionPHIRecipe directly in LV, without
needing to construction a whole RecurrenceDescriptor object.

Depends on
https://github.com/llvm/llvm-project/pull/141860
https://github.com/llvm/llvm-project/pull/141932
https://github.com/llvm/llvm-project/pull/142290
https://github.com/llvm/llvm-project/pull/142291

PR: https://github.com/llvm/llvm-project/pull/142322
2025-07-06 21:40:42 +01:00
Florian Hahn
c35fbb5460
[VPlan] Use VPReductionPHIRecipe::isOrdered instead of CM (NFC).
Directly retrieve isOrdered from the reduction phi recipe instead of
going through the legacy cost model.

Split off as suggested in
https://github.com/llvm/llvm-project/pull/142322.
2025-07-06 20:49:34 +01:00
Florian Hahn
c5fff132d0
[LV] Add LVL::getRecurrenceDescriptor (NFC).
Split off adding helper to retrieve RecurrenceDescriptor as suggested
from https://github.com/llvm/llvm-project/pull/142322.
2025-07-06 20:31:38 +01:00
Florian Hahn
cf06047231
[LV] Remove AddedAnyChecks, check directly instead (NFC).
As suggested in https://github.com/llvm/llvm-project/pull/143879, remove
AddedAnyChecks member and directly check if there are any relevant
runtime check blocks.
2025-07-06 20:19:46 +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
Rahul Joshi
b38de6c18e
[NFCI][LLVM] Adopt ArrayRef::consume_front() in a few places (#146793) 2025-07-04 10:42:14 -07:00
Austin
a550fef906
[llvm] Use llvm::fill instead of std::fill(NFC) (#146911)
Use llvm::fill instead of std::fill
2025-07-04 14:10:28 +08: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
Luke Lau
61a0653cc6
[VPlan] Fix first-order splices without header mask not using EVL (#146672)
This fixes a buildbot failure with EVL tail folding after #144666:
https://lab.llvm.org/buildbot/#/builders/132/builds/1653

For a first-order recurrence to be correct with EVL tail folding we need
to convert splices to vp splices with the EVL operand.
Originally we did this by looking for users of the header mask and its
users, and converting it in createEVLRecipe.

However after #144666 a FOR splice might not actually use the header
mask if it's based off e.g. an induction variable, and so we wouldn't
pick it up in createEVLRecipe.

This fixes this by converting FOR splices separately in a loop over all
recipes in the plan, regardless of whether or not it uses the header
mask.

I think there was some conflation in createEVLRecipe between what was an
optimisation and what was needed for correctness. Most of the transforms
in it just exist to optimize the mask away and we should still emit
correct code without them. So I've renamed it to make the separation
clearer.
2025-07-03 16:55:00 +01:00
Luke Lau
ec25a0568c
[VPlan] Don't convert VPWidenSelectRecipes to vp.select in EVL transform (#146695)
createEVLRecipe tries to optimise recipes that use the header mask by
replacing them with their VP equivalents and setting the EVL, allowing
the mask to be removed.

However we currently also convert widened selects to vp.select even
though they don't necessarily use the header mask.

Unlike vp.merge a vp.select only makes the "unused" lanes past EVL
poison, so it's not needed for correctness.

In the same vein as #127180, this patch removes the transform for
VPWidenSelectRecipes and keeps them as plain select instructions to
allow for more optimisations.

RISCVVLOptimizer will still be able to optimise away any VL toggles and
we end up with better code generation across llvm-test-suite and SPEC
CPU 2017.
2025-07-03 11:50:25 +01:00
Mel Chen
fcdb91e113
[VPlan] Remove redundant debug location setting in VPInterleaveRecipe::execute. nfc (#146670)
Remove it since we already set debug loc in
VPBasicBlock::executeRecipes.
2025-07-03 15:52:45 +08:00
Florian Hahn
4acdb8e14e
[VectorCombine] Scalarize extracts of ZExt if profitable. (#142976)
Add a new scalarization transform that tries to convert extracts of a
vector ZExt to a set of scalar shift and mask operations. This can be
profitable if the cost of extracting is the same or higher than the cost
of 2 scalar ops. This is the case on AArch64 for example.

For AArch64,this shows up in a number of workloads, including av1aom,
gmsh, minizinc and astc-encoder.

PR: https://github.com/llvm/llvm-project/pull/142976
2025-07-03 08:49:32 +01:00
Mel Chen
3e370452fd
[VPlan] Early assert for unsupported interleaved access features. nfc (#146669) 2025-07-03 15:31:53 +08:00
Luke Lau
7931a8f102
[VectorCombine] Scalarize vector intrinsics with scalar arguments (#146530)
Some intrinsics like llvm.abs or llvm.powi have a scalar argument even
when the overloaded type is a vector.
This patch handles these in scalarizeOpOrCmp to allow scalarizing them.

In the test the leftover vector powi isn't folded away to poison, this
should be fixed in a separate patch.
2025-07-02 16:48:53 +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
Simon Pilgrim
651c5208f8 VPlanRecipes.cpp - fix "'llvm::VPExpressionRecipe::computeCost': not all control paths return a value" MSVC warning. NFC. 2025-07-02 09:59:01 +01:00
Florian Hahn
863e17a5be
[VPlan] Make Phi operand for VPReductionPHIRecipe optional (NFC).
VPReductionPHIRecipe doesn't rely on the underlying phi any longer,
allow empty underlying values when cloning. NFC at the moment but will
enable follow-up patches.
2025-07-01 22:49:27 +01:00
Florian Hahn
bcbc440712
[VPlan] Add missing VPWidenSelectto VPRecipeWithIRFlags::classof (NFC).
Add missing entry to VPRecipeWithIRFlags. NFC currently as it is never
called on VPWidenSelectRecipes currently.
2025-07-01 22:26:57 +01:00
Florian Hahn
829f2f2448
[VectorCombine] Mark function as changed if shuffle is created.
777d6b5de90b7e0 exposed a code path where a function is modified but not
marked accordingly. Make sure we return true from foldShuffleFromReductions
if only a shuffle has been inserted/replaced.

Should fix    https://lab.llvm.org/buildbot/#/builders/187/builds/7578.
2025-07-01 21:38:29 +01:00
Florian Hahn
777d6b5de9
[VectorCombine] Use InstSimplifyFolder to simplify instrs on creation. (#146350)
Update VectorCombine to use InstSimplifyFolder to simplify redundant
instructions on creation.

PR: https://github.com/llvm/llvm-project/pull/146350
2025-07-01 20:55:51 +01:00
Florian Hahn
6b3d2b629c
[VPlan] Add VPExpressionRecipe, replacing extended reduction recipes. (#144281)
This patch adds a new recipe to combine multiple recipes into an
'expression' recipe, which should be considered as single entity for
cost-modeling and transforms. The recipe needs to be 'decomposed', i.e.
replaced by its individual recipes before execute.

This subsumes VPExtendedReductionRecipe and
VPMulAccumulateReductionRecipe and should make it easier to extend to
include more types of bundled patterns, like e.g. extends folded into
loads or various arithmetic instructions, if supported by the target.

It allows avoiding re-creating the original recipes when converting to
concrete recipes, together with removing the need to record various
information. The current version of the patch still retains the original
printing matching VPExtendedReductionRecipe and
VPMulAccumulateReductionRecipe, but this specialized print could be
replaced with printing the bundled recipes directly.

PR: https://github.com/llvm/llvm-project/pull/144281
2025-07-01 20:44:50 +01: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
Luke Lau
4a2fa0847f
[VPlan] Support VPWidenIntOrFpInductionRecipes with EVL tail folding (#144666)
Following on from #118638, this handles widened induction variables with
EVL tail folding by setting the VF operand to be EVL, calculated in the
vector body.

We need to do this for correctness since with EVL tail folding the
number of elements processed in the penultimate iteration may not be VF,
but the runtime EVL, and we need take this into account when updating
the backedge value.

- Because the VF may now not be a live-in we need to move the insertion
point to just after the VFs definition
- We also need to avoid truncating it when it's the same size as the
step type, previously this wasn't a problem for live-ins.
- Also because the VF may be smaller than the IV type, since the EVL is
always i32, we may need to zext it.

On -march=rva23u64 -O3 we get 87.1% more loops vectorized on TSVC, and
42.8% more loops vectorized on SPEC CPU 2017
2025-07-01 12:29:24 +01:00
Florian Hahn
59a7185dd9
[VPlan] Truncate/Extend ComputeReductionResult at construction (NFC). (#141860)
Instead of looking up the narrower reduction type via getRecurrenceType
we can generate the needed extend directly at constructiond re-use the
truncated value from the loop.

PR: https://github.com/llvm/llvm-project/pull/141860
2025-06-30 22:39:17 +01:00
Florian Hahn
026aae7047
[VPlan] Infer reduction result types w/o accessing underlying phis.(NFC)
Remove another use of the underlying IR phi.
2025-06-30 21:29:29 +01:00
Luke Lau
f01a7936be
[VPlan] Replace all uses of VF when EVL tail folding. NFCI (#146339)
With EVL tail folding, any use of the VF live in should be replaced by
the EVL. Otherwise, it should likely be directly emitted as a constant
via VPTransformState::VF.

This strengthens the EVL transformation by replacing all uses of VF with
EVL and asserting that the only users are VPVectorEndPointerRecipe and
VPScalarIVStepsRecipe, the latter of which is new.

This should be NFC because even though we didn't previously replace the
EVL of VPScalarIVStepsRecipe, it's only used when unrolling which we
don't allow with EVL tail folding yet.
2025-06-30 13:47: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
20fbbd7675
[LV] Add support for cmp reductions with decreasing IVs. (#140451)
Similar to FindLastIV, add FindFirstIVSMin to support select (icmp(), x, y)
reductions where one of x or y is a decreasing induction, producing a SMin
 reduction. It uses signed max as sentinel value.

PR: https://github.com/llvm/llvm-project/pull/140451
2025-06-29 11:17:03 +01:00
Florian Hahn
bdb299a67e
[VPlan] Simplify code in single scalar transform code (NFC).
Adjust code as suggested post-commit 3b7b95f78e2.

3b7b95f78e (r160997427)
2025-06-28 22:53:14 +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
vporpo
1eacdddc0c
[SandboxVec][SeedCollector][NFC] Replace cl::opt flags with constructor args (#143206)
The `SeedCollector` class gets two new arguments: `CollectStores` and
`CollectLoads`. These replace the `sbvec-collect-seeds` cl::opt flag.
This is done to help with reusing the SeedCollector class in a future
pass. The cl::opt flag is moved to the seed collection pass:
Passes/SeedCollection.cpp
2025-06-27 12:27:25 -07:00
Florian Hahn
3b7b95f78e
[VPlan] Support VPWidenSelectRecipe in narrowToSingleScalar.
VPWidenSelectRecipes are single scalars if all their operands are. Add
support for narrowing them to a single scalar VPReplicateRecipe.

This fixes a crash after
https://github.com/llvm/llvm-project/pull/142433 (aa24029319083) when
due to a replicate recipe not being converted to single-scalar being
hoisted to the vector preheader.
2025-06-27 15:42:42 +01:00
Ramkumar Ramachandra
613804cca9
[LV] Improve code using [[maybe_unused]] (NFC) (#137138) 2025-06-27 10:58:17 +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
David Sherwood
6f43754e9c
[LV] Disable interleaving via hints for uncountable early exit loops (#145877)
Currently if the user enables interleaving during vectorisation of
uncountable early exit loops via the interleave_count pragma and the
enable-early-exit-vectorization option, it will miscompile. There is
ongoing work to fix this, but for now it seems safer to ignore the hint
until it is supported.

---------

Co-authored-by: Paul Walker <paul.walker@arm.com>
2025-06-27 09:09:55 +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