blob: 65f3c837f77210dbf7c072c2932edeb79ddc1efe [file] [log] [blame]
Florian Hahne60b36c2019-12-07 08:52:36 +00001//===- VPlanTransforms.h - Utility VPlan to VPlan transforms --------------===//
Florian Hahn3385caa2018-06-18 18:28:49 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Florian Hahn3385caa2018-06-18 18:28:49 +00006//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file provides utility VPlan to VPlan transformations.
11//===----------------------------------------------------------------------===//
12
Florian Hahne60b36c2019-12-07 08:52:36 +000013#ifndef LLVM_TRANSFORMS_VECTORIZE_VPLANTRANSFORMS_H
14#define LLVM_TRANSFORMS_VECTORIZE_VPLANTRANSFORMS_H
Florian Hahn3385caa2018-06-18 18:28:49 +000015
16#include "VPlan.h"
Florian Hahn2b55ef12025-01-29 10:50:01 +000017#include "VPlanVerifier.h"
serge-sans-paille1b89c832022-03-21 21:52:21 +010018#include "llvm/ADT/STLFunctionalExtras.h"
Florian Hahn2b55ef12025-01-29 10:50:01 +000019#include "llvm/Support/CommandLine.h"
Florian Hahn3385caa2018-06-18 18:28:49 +000020
21namespace llvm {
22
Florian Hahn978883d2021-12-10 09:55:09 +000023class InductionDescriptor;
Florian Hahn49999d42021-04-15 19:07:28 +010024class Instruction;
Florian Hahn978883d2021-12-10 09:55:09 +000025class PHINode;
Florian Hahn49999d42021-04-15 19:07:28 +010026class ScalarEvolution;
Florian Hahne1650c82022-12-23 12:51:20 +000027class PredicatedScalarEvolution;
Florian Hahnfc444dd2022-09-01 13:14:40 +010028class TargetLibraryInfo;
Florian Hahnc83fdc92023-02-08 15:49:29 +000029class VPBuilder;
Florian Hahn16910a22024-08-28 15:56:09 +010030class VPRecipeBuilder;
Kazu Hirataf0621b32025-04-17 16:23:51 -070031struct VFRange;
Florian Hahn49999d42021-04-15 19:07:28 +010032
Florian Hahn2b55ef12025-01-29 10:50:01 +000033extern cl::opt<bool> VerifyEachVPlan;
34
Florian Hahnae1e3532020-04-12 10:51:17 +010035struct VPlanTransforms {
Florian Hahn2b55ef12025-01-29 10:50:01 +000036 /// Helper to run a VPlan transform \p Transform on \p VPlan, forwarding extra
37 /// arguments to the transform. Returns the boolean returned by the transform.
38 template <typename... ArgsTy>
39 static bool runPass(bool (*Transform)(VPlan &, ArgsTy...), VPlan &Plan,
40 typename std::remove_reference<ArgsTy>::type &...Args) {
41 bool Res = Transform(Plan, Args...);
42 if (VerifyEachVPlan)
43 verifyVPlanIsValid(Plan);
44 return Res;
45 }
46 /// Helper to run a VPlan transform \p Transform on \p VPlan, forwarding extra
47 /// arguments to the transform.
48 template <typename... ArgsTy>
49 static void runPass(void (*Fn)(VPlan &, ArgsTy...), VPlan &Plan,
50 typename std::remove_reference<ArgsTy>::type &...Args) {
51 Fn(Plan, Args...);
52 if (VerifyEachVPlan)
53 verifyVPlanIsValid(Plan);
54 }
55
Florian Hahnbc03d6c2025-04-16 13:30:45 +020056 /// Replace loops in \p Plan's flat CFG with VPRegionBlocks, turing \p Plan's
57 /// flat CFG into a hierarchical CFG. It also creates a VPValue expression for
58 /// the original trip count. It will also introduce a dedicated VPBasicBlock
59 /// for the vector pre-header as well a VPBasicBlock as exit block of the
60 /// region (middle.block). If a check is needed to guard executing the scalar
Florian Hahnfd267082025-03-09 15:05:35 +000061 /// epilogue loop, it will be added to the middle block, together with
62 /// VPBasicBlocks for the scalar preheader and exit blocks. \p InductionTy is
63 /// the type of the canonical induction and used for related values, like the
64 /// trip count expression.
Florian Hahnbc03d6c2025-04-16 13:30:45 +020065 static void createLoopRegions(VPlan &Plan, Type *InductionTy,
66 PredicatedScalarEvolution &PSE,
67 bool RequiresScalarEpilogueCheck,
68 bool TailFolded, Loop *TheLoop);
Florian Hahnfd267082025-03-09 15:05:35 +000069
Florian Hahn3385caa2018-06-18 18:28:49 +000070 /// Replaces the VPInstructions in \p Plan with corresponding
Florian Hahn2e13ec52025-03-19 21:35:15 +000071 /// widen recipes. Returns false if any VPInstructions could not be converted
72 /// to a wide recipe if needed.
73 static bool tryToConvertVPInstructionsToVPRecipes(
74 VPlanPtr &Plan,
75 function_ref<const InductionDescriptor *(PHINode *)>
76 GetIntOrFpInductionDescriptor,
77 ScalarEvolution &SE, const TargetLibraryInfo &TLI);
Florian Hahn65d3dd72021-05-24 14:14:08 +010078
Florian Hahn2dfb1c62024-10-23 13:12:03 -070079 /// Try to have all users of fixed-order recurrences appear after the recipe
80 /// defining their previous value, by either sinking users or hoisting recipes
81 /// defining their previous value (and its operands). Then introduce
82 /// FirstOrderRecurrenceSplice VPInstructions to combine the value from the
83 /// recurrence phis and previous values.
Florian Hahna6d67302023-08-04 13:21:19 +010084 /// \returns true if all users of fixed-order recurrences could be re-arranged
85 /// as needed or false if it is not possible. In the latter case, \p Plan is
86 /// not valid.
87 static bool adjustFixedOrderRecurrences(VPlan &Plan, VPBuilder &Builder);
88
89 /// Clear NSW/NUW flags from reduction instructions if necessary.
90 static void clearReductionWrapFlags(VPlan &Plan);
91
Florian Hahn8ec40672024-09-21 19:47:37 +010092 /// Explicitly unroll \p Plan by \p UF.
93 static void unrollByUF(VPlan &Plan, unsigned UF, LLVMContext &Ctx);
94
Florian Hahna6d67302023-08-04 13:21:19 +010095 /// Optimize \p Plan based on \p BestVF and \p BestUF. This may restrict the
96 /// resulting plan to \p BestVF and \p BestUF.
97 static void optimizeForVFAndUF(VPlan &Plan, ElementCount BestVF,
98 unsigned BestUF,
99 PredicatedScalarEvolution &PSE);
100
101 /// Apply VPlan-to-VPlan optimizations to \p Plan, including induction recipe
102 /// optimizations, dead recipe removal, replicate region optimizations and
103 /// block merging.
David Sherwoodf3029b32024-09-13 12:09:00 +0100104 static void optimize(VPlan &Plan);
Florian Hahna6d67302023-08-04 13:21:19 +0100105
Florian Hahn79272ec2023-03-08 20:11:27 +0100106 /// Wrap predicated VPReplicateRecipes with a mask operand in an if-then
Florian Hahneca14a82023-03-16 17:06:44 +0000107 /// region block and remove the mask operand. Optimize the created regions by
108 /// iteratively sinking scalar operands into the region, followed by merging
109 /// regions until no improvements are remaining.
Florian Hahn371bb2c2023-03-18 20:30:48 +0000110 static void createAndOptimizeReplicateRegions(VPlan &Plan);
Florian Hahn505ad032021-12-10 13:56:43 +0000111
Florian Hahn97687b72023-09-25 13:34:44 +0100112 /// Replace (ICMP_ULE, wide canonical IV, backedge-taken-count) checks with an
113 /// (active-lane-mask recipe, wide canonical IV, trip-count). If \p
114 /// UseActiveLaneMaskForControlFlow is true, introduce an
115 /// VPActiveLaneMaskPHIRecipe. If \p DataAndControlFlowWithoutRuntimeCheck is
116 /// true, no minimum-iteration runtime check will be created (during skeleton
117 /// creation) and instead it is handled using active-lane-mask. \p
118 /// DataAndControlFlowWithoutRuntimeCheck implies \p
119 /// UseActiveLaneMaskForControlFlow.
120 static void addActiveLaneMask(VPlan &Plan,
121 bool UseActiveLaneMaskForControlFlow,
122 bool DataAndControlFlowWithoutRuntimeCheck);
123
Florian Hahn70535f52023-12-02 16:12:38 +0000124 /// Insert truncates and extends for any truncated recipe. Redundant casts
125 /// will be folded later.
126 static void
127 truncateToMinimalBitwidths(VPlan &Plan,
David Sherwoodf3029b32024-09-13 12:09:00 +0100128 const MapVector<Instruction *, uint64_t> &MinBWs);
Florian Hahn70535f52023-12-02 16:12:38 +0000129
Florian Hahndebca7e2024-02-14 12:28:58 +0000130 /// Drop poison flags from recipes that may generate a poison value that is
131 /// used after vectorization, even when their operands are not poison. Those
132 /// recipes meet the following conditions:
133 /// * Contribute to the address computation of a recipe generating a widen
134 /// memory load/store (VPWidenMemoryInstructionRecipe or
135 /// VPInterleaveRecipe).
136 /// * Such a widen memory load/store has at least one underlying Instruction
137 /// that is in a basic block that needs predication and after vectorization
138 /// the generated instruction won't be predicated.
139 /// Uses \p BlockNeedsPredication to check if a block needs predicating.
140 /// TODO: Replace BlockNeedsPredication callback with retrieving info from
141 /// VPlan directly.
142 static void dropPoisonGeneratingRecipes(
Florian Hahn2b55ef12025-01-29 10:50:01 +0000143 VPlan &Plan,
144 const std::function<bool(BasicBlock *)> &BlockNeedsPredication);
Alexey Bataev413a66f2024-04-04 18:30:17 -0400145
146 /// Add a VPEVLBasedIVPHIRecipe and related recipes to \p Plan and
147 /// replaces all uses except the canonical IV increment of
148 /// VPCanonicalIVPHIRecipe with a VPEVLBasedIVPHIRecipe.
149 /// VPCanonicalIVPHIRecipe is only used to control the loop after
150 /// this transformation.
Shih-Po Hung0338c552024-05-25 08:22:49 +0800151 /// \returns true if the transformation succeeds, or false if it doesn't.
Alexey Bataevf148d572024-10-18 15:51:49 -0400152 static bool
153 tryAddExplicitVectorLength(VPlan &Plan,
154 const std::optional<unsigned> &MaxEVLSafeElements);
Florian Hahn16910a22024-08-28 15:56:09 +0100155
156 // For each Interleave Group in \p InterleaveGroups replace the Recipes
157 // widening its memory instructions with a single VPInterleaveRecipe at its
158 // insertion point.
159 static void createInterleaveGroups(
Florian Hahn7f746512024-10-06 22:53:13 +0100160 VPlan &Plan,
161 const SmallPtrSetImpl<const InterleaveGroup<Instruction> *>
162 &InterleaveGroups,
Florian Hahn2b55ef12025-01-29 10:50:01 +0000163 VPRecipeBuilder &RecipeBuilder, const bool &ScalarEpilogueAllowed);
Florian Hahn53266f72024-09-22 21:50:14 +0100164
165 /// Remove dead recipes from \p Plan.
166 static void removeDeadRecipes(VPlan &Plan);
Florian Hahna7fda0e2024-12-03 14:53:51 +0000167
Florian Hahn5fae4082024-12-11 21:11:05 +0000168 /// Update \p Plan to account for the uncountable early exit block in \p
169 /// UncountableExitingBlock by
170 /// * updating the condition exiting the vector loop to include the early
171 /// exit conditions
172 /// * splitting the original middle block to branch to the early exit block
173 /// if taken.
David Sherwood3bc2dad2025-01-30 10:37:00 +0000174 static void handleUncountableEarlyExit(VPlan &Plan, ScalarEvolution &SE,
Florian Hahn5fae4082024-12-11 21:11:05 +0000175 Loop *OrigLoop,
176 BasicBlock *UncountableExitingBlock,
Elvis Wang69ade7c2025-04-18 06:51:36 +0800177 VPRecipeBuilder &RecipeBuilder,
178 VFRange &Range);
Florian Hahn5fae4082024-12-11 21:11:05 +0000179
Florian Hahn54b33eb2025-04-14 22:20:44 +0100180 /// Lower abstract recipes to concrete ones, that can be codegen'd. Use \p
181 /// CanonicalIVTy as type for all un-typed live-ins in VPTypeAnalysis.
182 static void convertToConcreteRecipes(VPlan &Plan, Type &CanonicalIVTy);
Florian Hahn2c871332025-01-19 19:32:02 +0000183
Florian Hahn6ff8a062025-02-08 13:33:46 +0000184 /// Perform instcombine-like simplifications on recipes in \p Plan. Use \p
185 /// CanonicalIVTy as type for all un-typed live-ins in VPTypeAnalysis.
186 static void simplifyRecipes(VPlan &Plan, Type &CanonicalIVTy);
187
Florian Hahn2c871332025-01-19 19:32:02 +0000188 /// If there's a single exit block, optimize its phi recipes that use exiting
189 /// IV values by feeding them precomputed end values instead, possibly taken
190 /// one step backwards.
191 static void
192 optimizeInductionExitUsers(VPlan &Plan,
193 DenseMap<VPValue *, VPValue *> &EndValues);
Florian Hahn4277c212025-02-26 13:57:51 +0000194
Florian Hahn62994c32025-03-12 22:03:18 +0000195 /// Add explicit broadcasts for live-ins and VPValues defined in \p Plan's entry block if they are used as vectors.
196 static void materializeBroadcasts(VPlan &Plan);
Florian Hahnc73ad7b2025-03-20 19:41:36 +0000197
198 /// Try to convert a plan with interleave groups with VF elements to a plan
199 /// with the interleave groups replaced by wide loads and stores processing VF
200 /// elements, if all transformed interleave groups access the full vector
201 /// width (checked via \o VectorRegWidth). This effectively is a very simple
202 /// form of loop-aware SLP, where we use interleave groups to identify
203 /// candidates.
204 static void narrowInterleaveGroups(VPlan &Plan, ElementCount VF,
205 unsigned VectorRegWidth);
Florian Hahn3385caa2018-06-18 18:28:49 +0000206};
207
208} // namespace llvm
209
Florian Hahne60b36c2019-12-07 08:52:36 +0000210#endif // LLVM_TRANSFORMS_VECTORIZE_VPLANTRANSFORMS_H