summaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Vectorize/VPlan.cpp
AgeCommit message (Collapse)Author
2025-06-26[VPlan] Speed up VPSlotTracker by using ModuleSlotTracker (#139881)Igor Kirillov
Currently, when VPSlotTracker is initialized with a VPlan, its assignName method calls printAsOperand on each underlying instruction. Each such call recomputes slot numbers for the entire function, leading to O(N × M) complexity, where M is the number of instructions in the loop and N is the number of instructions in the function. This results in slow debug output for large loops. For example, printing costs of all instructions becomes O(M² × N), which is especially painful when enabling verbose dumps. This patch improves debugging performance by caching slot numbers using ModuleSlotTracker. It avoids redundant recomputation and makes debug output significantly faster.
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[VPlan] Format some print forms.NFC (#144644)LiqinWeng
2025-06-21[VPlan] Update packScalarIntoVector to take and return wide value (NFC)Florian Hahn
Make the function more flexible in preparation for new users.
2025-06-18Revert "[VPlan] Remove unnecessary DomTreeUpdater flush (NFC)." (#144758)Arthur Eubanks
This reverts commit 2e337349f436d75af112c081df5ec683871cbcc8. Causes breakages internally, will post reproducer later.
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-15[VPlan] Mark VPFirstOrderRecurrencePHI as not reading/writing memory.Florian Hahn
First-order recurrence phis don't have side-effects and don't read or write memory. Mark them as such.
2025-06-13[LV] Use getFixedValue instead of getKnownMinValue when appropriate (#143526)David Sherwood
There are many places in VPlan and LoopVectorize where we use getKnownMinValue to discover the number of elements in a vector. Where we expect the vector to have a fixed length, I have used the stronger getFixedValue call. I believe this is clearer and adds extra protection in the form of an assert in getFixedValue that the vector is not scalable. While looking at VPFirstOrderRecurrencePHIRecipe::computeCost I also took the liberty of simplifying the code. In theory I believe this patch should be NFC, but I'm reluctant to add that to the title in case we're just missing tests for some of the VPlan changes. I built and ran the LLVM test suite when targeting neoverse-v1 and it seemed ok.
2025-06-12[DLCov][NFC] Propagate annotated DebugLocs through transformations (#138047)Stephen Tozer
Part of the coverage-tracking feature, following #107279. In order for DebugLoc coverage testing to work, we firstly have to set annotations for intentionally-empty DebugLocs, and secondly we have to ensure that we do not drop these annotations as we propagate DebugLocs throughout compilation. As the annotations exist as part of the DebugLoc class, and not the underlying DILocation, they will not survive a DebugLoc->DILocation->DebugLoc roundtrip. Therefore this patch modifies a number of places in the compiler to propagate DebugLocs directly rather than via the underlying DILocation. This has no effect on the output of normal builds; it only ensures that during coverage builds, we do not drop incorrectly annotations and therefore create false positives. The bulk of these changes are in replacing DILocation::getMergedLocation(s) with a DebugLoc equivalent, and in changing the IRBuilder to store a DebugLoc directly rather than storing DILocations in its general Metadata array. We also use a new function, `DebugLoc::orElse`, which selects the "best" DebugLoc out of a pair (valid location > annotated > empty), preferring the current DebugLoc on a tie - this encapsulates the existing behaviour at a few sites where we _may_ assign a DebugLoc to an existing instruction, while extending the logic to handle annotation DebugLocs at the same time.
2025-06-05[VPlan] Remove unnecessary DomTreeUpdater flush (NFC).Florian Hahn
The current version does not need the explicit flush at this point.
2025-06-03[VPlan] Remove CanonicalIV when dissolving loop regions (NFC). (#142372)Florian Hahn
Directly replace the canonical IV when we dissolve the containing region. That ensures that it won't get removed before the region gets removed, which would result in an invalid region. This removes the current ordering constraint between convertToConcreteRecipes and dissolving regions. PR: https://github.com/llvm/llvm-project/pull/142372
2025-05-24[VPlan] Replace VPRegionBlock with explicit CFG before execute (NFCI). (#117506)Florian Hahn
Building on top of https://github.com/llvm/llvm-project/pull/114305, replace VPRegionBlocks with explicit CFG before executing. This brings the final VPlan closer to the IR that is generated and helps to simplify codegen. It will also enable further simplifications of phi handling during execution and transformations that do not have to preserve the canonical IV required by loop regions. This for example could include replacing the canonical IV with an EVL based phi while completely removing the original canonical IV. PR: https://github.com/llvm/llvm-project/pull/117506
2025-05-23Reapply "[VPlan] Support cloning initial VPlan (NFC)."Florian Hahn
This reverts commit 204252e2df80876702616518a5154dccacf3ebac. Recommit with a fix for the leak in a unit test.
2025-05-18Revert "[VPlan] Support cloning initial VPlan (NFC)."Florian Hahn
This reverts commit 5fa985e751c8f890fff31e190473aeeb6f7a9fc5. Revert as this seems to introduce a call to a pure virtual function on a few configs, e.g. https://lab.llvm.org/buildbot/#/builders/169/builds/11535
2025-05-18[VPlan] Support cloning initial VPlan (NFC).Florian Hahn
Support cloning VPlans as they are created by the initial buildVPlan, i.e. scalar header not yet connected and no trip-count set. This is not used yet but will in follow-up changes/ Also add a unit test for cloning & printing.
2025-05-16[VPlan] Also use original parent loop for exit VPBBs.Florian Hahn
When vectorizing loops with early exits that is nested within another one, one of the loop exits may be outside both loops, so setting adding it to the parent loop is incorrect. Also use the original parent loop for exit blocks.
2025-05-16[VPlan] Rename isUniform(AfterVectorization) to isSingleScalar (NFC). (#140134)Florian Hahn
Update the naming in VPReplicateRecipe and vputils to the more accurate isSingleScalar, as the functions check for cases where only a single scalar is needed, either because it produces the same value for all lanes or has only their first lane used. Discussed in https://github.com/llvm/llvm-project/pull/139150. PR: https://github.com/llvm/llvm-project/pull/140134
2025-05-09[VPlan] Manage noalias/alias_scope metadata in VPlan. (#136450)Florian Hahn
Use VPIRMetadata added in https://github.com/llvm/llvm-project/pull/135272 to also manage no-alias metadata added by versioning. Note that this means we have to build the no-alias metadata up-front once. If it is not used, it will be discarded automatically. This also fixes a case where incorrect metadata was added to wide loads/stores that got converted from an interleave group. Compile-time impact is neutral: https://llvm-compile-time-tracker.com/compare.php?from=38bf1af41c5425a552a53feb13c71d82873f1c18&to=2fd7844cfdf5ec0f1c2ce0b9b3ae0763245b6922&stat=instructions:u
2025-05-05[VPlan] Replace getPreheaderBBFor with getCFGPredecessor. (NFC)Florian Hahn
Replace existing uses of getPreheaderBBFor with the newly added more general getCFGPredecessor.
2025-05-04[VPlan] Add VPPhiAccessors to provide interface for phi recipes (NFC) (#129388)Florian Hahn
Add a VPPhiAccessors class to provide interfaces to access incoming values and blocks. The first user is VPWidenPhiRecipe, with the other phi-like recipes following soon. This will also be used to verify def-use chains where users are phi-like recipes, simplifying https://github.com/llvm/llvm-project/pull/124838. PR: https://github.com/llvm/llvm-project/pull/129388
2025-05-04[Transforms] Remove unused local variables (NFC) (#138442)Kazu Hirata
2025-05-03[VPlan] Move scalarizeInstruction out of ILV (NFC).Florian Hahn
15bb1db4a9830 removed the last dependency on ILV, move the code out of ILV in preparation of consolidating in VPlanRecipes.cpp.
2025-04-24[VPlan] Manage instruction metadata in VPlan. (#135272)Florian Hahn
Add a new helper to manage IR metadata that can be progated to generated instructions for recipes. This helps to remove a number of remaining uses of getUnderlyingInstr during VPlan execution. PR: https://github.com/llvm/llvm-project/pull/135272
2025-04-18[VPlan] Only generate exit blocks for unique exit blocks.Florian Hahn
Make sure we don't generate unnecessary blocks.
2025-04-11[LV] Reduce register usage for scaled reductions (#133090)Sam Tebbs
This PR accounts for scaled reductions in `calculateRegisterUsage` to reflect the fact that the number of lanes in their output is smaller than the VF. Depends on https://github.com/llvm/llvm-project/pull/126437
2025-04-07[VPlan] Introduce and use VPValue::replaceUsesOfWith (NFC).Florian Hahn
Adds an API matching LLVM's IR Value, which simplifies some code a bit.
2025-04-07[VPlan] Populate ExitBlocks when cloning VPlan (NFC).Florian Hahn
Update VPlan::duplicate to add cloned exit blocks to ExitBlocks. Currently there are no uses of the exit blocks after cloning so this is NFC at the moment.
2025-04-06Reapply "[LV] Don't add blocks to loop in GeneratedRTChecks (NFC)."Florian Hahn
This reverts commit 46a2f4174a051f29a09dbc3844df763571c67309. Recommits 2fd6f8fb5e3a with corresponding VPlan change to ensure LoopInfo is updated for all blocks during VPlan execution if needed.
2025-04-06[VPlan] Use ExitBocks to check in VPlan::isExitBlock (NFC).Florian Hahn
Exit blocks of the VPlan are now hold in ExitBlocks. Use it to check if a block is an exit block. Otherwise we currently mis-classify the scalar loop header also as exit block, as it is not explicitly connected to the exit blocks. NFC at the moment, as the helper currently is never queried with the scalar header, but that will change in the future.
2025-04-05[VPlan] Set debug location for recipes in VPBB::executeRecipes.Florian Hahn
Set the debug location for each recipe before executing the recipe, instead of ad-hoc setting the debug location during individual recipe execution. This simplifies the code and ensures that all recipe repsect the recipe's debug location. There are some minor changes, where previously we would re-use a previously set debug location.
2025-03-30[VPlan] Remove dead UF argument from VPTransformState ctor (NFC).Florian Hahn
2025-03-28[VPlan] Add new VPIRPhi overlay for VPIRInsts wrapping phi nodes (NFC). ↵Florian Hahn
(#129387) Add a new VPIRPhi subclass of VPIRInstruction, that purely serves as an overlay, to provide more convenient checking (via directly doing isa/dyn_cast/cast) and specialied execute/print implementations. Both VPIRInstruction and VPIRPhi share the same VPDefID, and are differentiated by the backing IR instruction. This pattern could alos be used to provide more specialized interfaces for some VPInstructions ocpodes, without introducing new, completely spearate recipes. An example would be modeling VPWidenPHIRecipe & VPScalarPHIRecip using VPInstructions opcodes and providing an interface to retrieve incoming blocks and values through a VPInstruction subclass similar to VPIRPhi. PR: https://github.com/llvm/llvm-project/pull/129387
2025-03-20[VPlan] Add transformation to narrow interleave groups.Florian Hahn
This patch adds a new narrowInterleaveGroups transfrom, which tries convert a plan with interleave groups with VF elements to a plan that instead replaces the interleave groups with wide loads and stores processing VF elements. This effectively is a very simple form of loop-aware SLP, where we use interleave groups to identify candidates. This initial version is quite restricted and hopefully serves as a starting point for how to best model those kinds of transforms. For now it only transforms load interleave groups feeding store groups. Depends on #106431. This lands the main parts of the approved https://github.com/llvm/llvm-project/pull/106441 as suggested to break things up a bit more.
2025-03-19[Transforms] Use *Set::insert_range (NFC) (#132056)Kazu Hirata
DenseSet, SmallPtrSet, SmallSet, SetVector, and StringSet recently gained C++23-style insert_range. This patch replaces: Dest.insert(Src.begin(), Src.end()); with: Dest.insert_range(Src); This patch does not touch custom begin like succ_begin for now.
2025-03-19[VPlan] Bail out on non-intrinsic calls in VPlanNativePath.Florian Hahn
Update initial VPlan-construction in VPlanNativePath in line with the inner loop path, in that it bails out when encountering constructs it cannot handle, like non-intrinsic calls. Fixes https://github.com/llvm/llvm-project/issues/131071.
2025-03-18[VPlan] Use CurrentParentLoop instead of looking up via CFG (NFC).Florian Hahn
There is no need to look up the current parent loop via LoopInfo and the vector preheader; we can simply use CurrentParentLoop.
2025-03-15[VPlan] Remove unused VPlanIngredient (NFC).Florian Hahn
VPlanIngredient is not used anymore, remove it.
2025-03-13[VPlan] Use VPInstruction for VPScalarPHIRecipe. (NFCI) (#129767)Florian Hahn
Now that all phi nodes manage their incoming blocks through the VPlan-predecessors, there should be no need for having a dedicate recipe, it should be sufficient to allow PHI opcodes in VPInstruction. Follow-ups will also migrate VPWidenPHIRecipe and possibly others, building on top of https://github.com/llvm/llvm-project/pull/129388. PR: https://github.com/llvm/llvm-project/pull/129767
2025-03-13[VPlan] Restrict hoisting of broadcast operations using VPDominatorTree ↵Mel Chen
(#117138) This patch restricts broadcast operations from being hoisted to the vector preheader unless the basic block that defines the broadcasted value properly dominates the vector preheader. This prevents potential use-before-definition issues when the broadcasted value is defined within the plan. VPDominatorTree is used to confirm this restriction while still allowing safe hoisting for broadcasted values defined outside the plan. Issue https://github.com/llvm/llvm-project/issues/117139
2025-03-13Revert "[LV] Limits the splat operations be hoisted must not be defined by a ↵Mel Chen
recipe. (#117138)" This reverts commit 1ff10fa82fff83bb2f0a5c1ffde6203b52bc9619.
2025-03-11[LV] Limits the splat operations be hoisted must not be defined by a recipe. ↵Mel Chen
(#117138) Issue https://github.com/llvm/llvm-project/issues/117139
2025-03-09[VPlan] Refactor VPlan creation, add transform introducing region (NFC). ↵Florian Hahn
(#128419) Create an empty VPlan first, then let the HCFG builder create a plain CFG for the top-level loop (w/o a top-level region). The top-level region is introduced by a separate VPlan-transform. This is instead of creating the vector loop region before building the VPlan CFG for the input loop. This simplifies the HCFG builder (which should probably be renamed) and moves along the roadmap ('buildLoop') outlined in [1]. As follow-up, I plan to also preserve the exit branches in the initial VPlan out of the CFG builder, including connections to the exit blocks. The conversion from plain CFG with potentially multiple exits to a single entry/exit region will be done as VPlan transform in a follow-up. This is needed to enable VPlan-based predication. Currently early exit support relies on building the block-in masks on the original CFG, because exiting branches and conditions aren't preserved in the VPlan. So in order to switch to VPlan-based predication, we will have to preserve them in the initial plain CFG, so the exit conditions are available explicitly when we convert to single entry/exit regions. Another follow-up is updating the outer loop handling to also introduce VPRegionBlocks for nested loops as transform. Currently the existing logic in the builder will take care of creating VPRegionBlocks for nested loops, but not the top-level loop. [1] https://llvm.org/devmtg/2023-10/slides/techtalks/Hahn-VPlan-StatusUpdateAndRoadmap.pdf PR: https://github.com/llvm/llvm-project/pull/128419
2025-03-01[VPlan] Update VPTransformState accessors to take const VPValue (NFC).Florian Hahn
This will enable using const VPValue * pointers are in more places.
2025-02-27[LoopVectorize] Use CodeSize as the cost kind for minsize (#124119)John Brawn
Functions marked with minsize should aim for minimum code size, so the vectorizer should use CodeSize for the cost kind and also the cost we compare should be the cost for the entire loop: it shouldn't be divided by the number of vector elements and block costs shouldn't be divided by the block probability. Possibly we should also be doing this for optsize as well, but there are a lot of tests that assume the current behaviour and the definition of optsize is less clear than minsize (for minsize the goal is to "keep the code size of this function as small as possible" whereas for optsize it's "keep the code size of this function low").
2025-02-26[VPlan] Introduce explicit broadcasts for live-ins. (#124644)Florian Hahn
Add a new VPInstruction::Broadcast opcode and use it to materialize explicit broadcasts of live-ins. The initial patch only materlizes the broadcasts if the vector preheader dominates all uses that need it. Later patches will pick the best valid insert point, thus retiring implicit hoisting of broadcasts from VPTransformsState::get(). PR: https://github.com/llvm/llvm-project/pull/124644
2025-02-25[VPlan] Construct immutable VPIRBBs for exit blocks at construction(NFC) ↵Florian Hahn
(#128374) Constract immutable VPIRBasicBlocks for all exit blocks up front and keep a list of them. Same as the scalar header, they are leaf nodes of the VPlan and won't change. Some exit blocks may be unreachable, e.g. if the scalar epilogue always executes or depending on optimizations. This simplifies both the way we retrieve the exit blocks as well as hooking up the exit blocks. PR: https://github.com/llvm/llvm-project/pull/128374
2025-02-24[LV] Remove some redundant casts (NFC).Florian Hahn
2025-02-18[VPlan] Build initial VPlan 0 using HCFGBuilder for inner loops. (NFC) (#124432)Florian Hahn
Use HCFGBuilder to build an initial VPlan 0, which wraps all input instructions in VPInstructions and update tryToBuildVPlanWithVPRecipes to replace the VPInstructions with widened recipes. At the moment, widened recipes are created based on the underlying instruction of the VPInstruction. Masks are also still created based on the input IR basic blocks and the loop CFG is flattened in the main loop processing the VPInstructions. This patch also incldues support for Switch instructions in HCFGBuilder using just a VPInstruction with Instruction::Switch opcode. There are multiple follow-ups planned: * Perform predication on the VPlan directly, * Unify code constructing VPlan 0 to be shared by both inner and outer loop code paths. * Construct VPlan 0 once, clone subsequent ones for VFs PR: https://github.com/llvm/llvm-project/pull/124432
2025-02-17[LV] Add initial support for vectorizing literal struct return values (#109833)Benjamin Maxwell
This patch adds initial support for vectorizing literal struct return values. Currently, this is limited to the case where the struct is homogeneous (all elements have the same type) and not packed. The users of the call also must all be `extractvalue` instructions. The intended use case for this is vectorizing intrinsics such as: ``` declare { float, float } @llvm.sincos.f32(float %x) ``` Mapping them to structure-returning library calls such as: ``` declare { <4 x float>, <4 x float> } @Sleef_sincosf4_u10advsimd(<4 x float>) ``` Or their widened form (such as `@llvm.sincos.v4f32` in this case). Implementing this required two main changes: 1. Supporting widening `extractvalue` 2. Adding support for vectorized struct types in LV * This is mostly limited to parts of the cost model and scalarization Since the supported use case is narrow, the required changes are relatively small.
2025-02-15[VPlan] Create IR basic block for middle.block in VPlan.Florian Hahn
Create a IR BB directly for the middle.block, instead of creating the IR BB during skeleton creation and then replacing the middle VPBB with a VPIRBB. This moves another part of skeleton creation to VPlan and simplififes the code slightly by removing code to disconnect the middle block and vector preheader + the corresponding DT update. NFC modulo IR block naming and block creation order, which changes the IR names for the blocks.