summaryrefslogtreecommitdiff
path: root/llvm/test/Transforms/LoopVectorize
AgeCommit message (Collapse)Author
2025-07-03[VPlan] Don't convert VPWidenSelectRecipes to vp.select in EVL transform ↵Luke Lau
(#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-02[LV] Add support for partial reductions without a binary op (#133922)David Sherwood
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[VPlan] Emit VPVectorEndPointerRecipe for reverse interleave pointer ↵Mel Chen
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-01[VPlan] Add VPExpressionRecipe, replacing extended reduction recipes. (#144281)Florian Hahn
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[LV] Use vscale for tuning to improve branch weight estimates (#144733)David Sherwood
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[VPlan] Support VPWidenIntOrFpInductionRecipes with EVL tail folding (#144666)Luke Lau
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-06-30[VPlan] Truncate/Extend ComputeReductionResult at construction (NFC). (#141860)Florian Hahn
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[VPlan] Replace all uses of VF when EVL tail folding. NFCI (#146339)Luke Lau
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-29[VPlan] Fix crash when trying to narrow interleave group storing const.Florian Hahn
Use dyn_cast_null to handle the case where an interleave groups stores a constant in any of its lanes.
2025-06-29Revert "[VPlan] Allow derived IVs and scalar-steps in narrowing interleave."Florian Hahn
This reverts commit 2787759ef2e41b19f8bfde06fe9a26b25d1f5834. This exposed a crash on some build bots. Revert to investigate.
2025-06-29[VPlan] Allow derived IVs and scalar-steps in narrowing interleave.Florian Hahn
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[LV] Add support for cmp reductions with decreasing IVs. (#140451)Florian Hahn
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-28[VPlan] Also visit VPBBs outside loop region when unrolling by VF.Florian Hahn
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-27[LV] Add additional tests for narrowing interleave groups.Florian Hahn
Add additional test coverage for narrowing interleave groups with derived IVs & scalar steps.
2025-06-27[VPlan] Support VPWidenSelectRecipe in narrowToSingleScalar.Florian Hahn
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[LV] Enable auto-vectorisation of loops with uncountable exits (#133099)David Sherwood
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[LV] Fix test issue caused by #145877 (#146041)David Sherwood
2025-06-27[LV] Disable interleaving via hints for uncountable early exit loops (#145877)David Sherwood
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[VPlan] Handle FirstActiveLane when unrolling. (#145394)Florian Hahn
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-26[VPlan] Handle AnyOf when unrolling. (#145340)Florian Hahn
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[VPlan] Unroll VPReplicateRecipe by VF. (#142433)Florian Hahn
Explicitly unroll VPReplicateRecipes outside replicate regions by VF, replacing them by VF single-scalar recipes. Extracts for operands are added as needed and the scalar results are combined to a vector using a new BuildVector VPInstruction. It also adds a few folds to simplify unnecessary extracts/BuildVectors. It also adds a BuildStructVector opcode for handling of calls that have struct return types. VPReplicateRecipe in replicate regions can will be unrolled as follow up, turing non-single-scalar VPReplicateRecipes into 'abstract', i.e. not executable. PR: https://github.com/llvm/llvm-project/pull/142433
2025-06-25[LV] Update test after 4ac4726d00.Florian Hahn
Update missed test checks after #144644.
2025-06-25[Verifier] Always verify all assume bundles. (#145586)Florian Hahn
For some reason, some of the checks for specific assumbe bundle elements exit early if the check pass, meaning we don't verify other entries. Replace the early returns with early continues. This also requires removing some tests that are currently rejected. They will be added back as part of https://github.com/llvm/llvm-project/pull/128436. PR: https://github.com/llvm/llvm-project/pull/145586
2025-06-24[LV] Replace redundant ExtractLastElement of reduction result (NFC).Florian Hahn
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-23[LAA] Be more careful when evaluating AddRecs at symbolic max BTC. (#128061)Florian Hahn
Evaluating AR at the symbolic max BTC may wrap and create an expression that is less than the start of the AddRec due to wrapping (for example consider MaxBTC = -2). If that's the case, set ScEnd to -(EltSize + 1). ScEnd will get incremented by EltSize before returning, so this effectively sets ScEnd to unsigned max. Note that LAA separately checks that accesses cannot not wrap (52ded672492, https://github.com/llvm/llvm-project/pull/127543), so unsigned max represents an upper bound. When there is a computable backedge-taken count, we are guaranteed to execute the number of iterations, and if any pointer would wrap it would be UB (or the access will never be executed, so cannot alias). It includes new tests from the previous discussion that show a case we wrap with a BTC, but it is UB due to the pointer after the object wrapping (in `evaluate-at-backedge-taken-count-wrapping.ll`) When we have only a maximum backedge taken count, we instead try to use dereferenceability information to determine if the pointer access must be in bounds for the maximum backedge taken count. PR: https://github.com/llvm/llvm-project/pull/128061
2025-06-23[LV] Add tests showing incorrect vector interleaving with early exits.Florian Hahn
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[LV] Extend FindLastIV to unsigned case (#141752)Ramkumar Ramachandra
Split the FindLastIV RecurKind into SMax and UMax variants, depending on the reduction op produced.
2025-06-22[LV] Add tests with fmax reductions without fast-math flags.Florian Hahn
Adds extra tests with fmax reductions without fast-math flags for upcoming patches.
2025-06-22[LV] Add additional tests for replicating calls returning structs.Florian Hahn
Add additional test coverage for replicating calls return structs, in particular cases where the number of struct elements does not match the VF. Extra test coverage for https://github.com/llvm/llvm-project/pull/142433.
2025-06-22[VPlan] Support matching constants in narrowInterleaveGroups.Florian Hahn
Matching constants can trivially be broadcasted, allow them if the same constant is used for all recipes in a bundle.
2025-06-21[LV] Add more tests for narrowing interleave groups with live-ins.Florian Hahn
2025-06-21[VPlan] Use EMIT-SCALAR when printing casts.Florian Hahn
Split off EMIT-SCALAR printing changes from already approved https://github.com/llvm/llvm-project/pull/140623. Currently all casts are single scalars, this brings printing in line with printing for other VPInstructions.
2025-06-20[VPlan] Simplify ExtractLastElement(Broadcast(A)) -> A.Florian Hahn
Remove trivial ExtractLastElement VPInstructions.
2025-06-20[LV] Consider whether vscale is a known power of two for iteration check ↵Philip Reames
(#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[VPlan] Use createScalarZExtOrTrunc when expanding expandVPWidenIntOrFpInductionLuke Lau
Split off from #144666
2025-06-20[LV] Regenerate uniform_across_vf* check lines.Florian Hahn
Re-generate check lines to reduce diff in upcoming changes. Also filters out the code after scalar.ph:, which is dead.
2025-06-20[LV] Add early-exit-with-store tests (#140899)Graham Hunter
Adds some additional LoopVectorizeLegality tests for early exit loops with a store that we don't vectorize. Test precommit split from #137774
2025-06-20[LV] Stengthen loop-invariance checks in isPredicatedInst (#140744)Ramkumar Ramachandra
Check loop-invariance against SCEV as well.
2025-06-20[LV] Don't mark ptrs as safe to speculate if fed by UB/poison op. (#143204)Florian Hahn
Add additional checks before marking pointers safe to load speculatively. If some computations feeding the pointer may trigger UB, we cannot load the pointer speculatively, because we cannot compute the address speculatively. The UB triggering instructions will be predicated, but if the predicated block does not execute the result is poison. Similarly, we also cannot load the pointer speculatively if it may be poison. The patch also checks if any of the operands defined outside the loop may be poison when entering the loop. We *don't* need to check if any operation inside the loop may produce poison due to flags, as those will be dropped if needed. There are some types of instructions inside the loop that can produce poison independent of flags. Currently loads are also checked, not sure if there's a convenient API to check for all such operands. Fixes https://github.com/llvm/llvm-project/issues/142957. PR: https://github.com/llvm/llvm-project/pull/143204
2025-06-20[VPlan] Remove redundant ExtractLastElement from vector-to-scalar VPI.Florian Hahn
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-19[LV] Add tests interleaving extended and multiply/accumulate reductions.Florian Hahn
Add missing test coverage for interleaving with VPExtendedReduction/VPMulAccumulateReduction recipes. Adds missing test coverage in preparation for https://github.com/llvm/llvm-project/pull/144281.
2025-06-19[VPlan] Fix handling of ReductionStartVector for rdxs when unrolling.Florian Hahn
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[LLVM][IRBuilder] Use NUW arithmetic for Create{ElementCount,TypeSize}. ↵Paul Walker
(#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[LV] Add interleaving test with partial reductions and non-const start.Florian Hahn
Add test coverage for mis-compile after https://github.com/llvm/llvm-project/pull/142290.
2025-06-19[LV][NFC] Add branch weight test showing incorrect behaviour (#144682)David Sherwood
This patch adds a test that shows incorrect branch weights being set in function EpilogueVectorizerEpilogueLoop::emitMinimumVectorEpilogueIterCountCheck
2025-06-18[LoopVectorize] Vectorize fixed-order recurrence with vscale x 1. (#142772)Mel Chen
When the fixed-order recurrence phi is live-out from the loop, the vectorizer uses VPInstruction::ExtractPenultimateElement to extract the penultimate element from the recurrence vector. However, this is not feasible when the VF is vscale x 1, since vscale could be 1, making the vector contain only one element. This patch changes the behavior for vscale x 1 by extracting the last element from the vector produced by splicing the recurrence phi and the previous value. This ensures we can still determine the correct live-out value of the recurrence phi.
2025-06-17[VPlan] Expand VPWidenIntOrFpInductionRecipe into separate recipes (#118638)Luke Lau
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[AArch64][VecLib] Add libmvec support for AArch64 targets (#143696)Mary Kassayova
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](https://github.com/bminor/glibc/blob/96abd59bf2a11ddd4e7ccaac840ec13c0b62d3ba/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-16[VPlan] Simplify trivial VPFirstOrderRecurrencePHI recipes.Florian Hahn
VPFirstOrderRecurrencePHIRecipes where the incoming values are the same can be simplified and removed. Fixes https://github.com/llvm/llvm-project/issues/144212. The new test is added together with other related tests from first-order-recurrence.ll
2025-06-16[LV] Update check to find epilogue resume value to check all incoming.Florian Hahn
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.