LLVM 22.0.0git
VPlanUtils.h
Go to the documentation of this file.
1//===- VPlanUtils.h - VPlan-related utilities -------------------*- C++ -*-===//
2//
3// 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
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_TRANSFORMS_VECTORIZE_VPLANUTILS_H
10#define LLVM_TRANSFORMS_VECTORIZE_VPLANUTILS_H
11
12#include "VPlan.h"
14
15namespace llvm {
16class ScalarEvolution;
17class SCEV;
18} // namespace llvm
19
20namespace llvm {
21
22namespace vputils {
23/// Returns true if only the first lane of \p Def is used.
24bool onlyFirstLaneUsed(const VPValue *Def);
25
26/// Returns true if only the first part of \p Def is used.
27bool onlyFirstPartUsed(const VPValue *Def);
28
29/// Returns true if only scalar values of \p Def are used by all users.
30bool onlyScalarValuesUsed(const VPValue *Def);
31
32/// Get or create a VPValue that corresponds to the expansion of \p Expr. If \p
33/// Expr is a SCEVConstant or SCEVUnknown, return a VPValue wrapping the live-in
34/// value. Otherwise return a VPExpandSCEVRecipe to expand \p Expr. If \p Plan's
35/// pre-header already contains a recipe expanding \p Expr, return it. If not,
36/// create a new one.
38
39/// Return the SCEV expression for \p V. Returns SCEVCouldNotCompute if no
40/// SCEV expression could be constructed.
42 const Loop *L = nullptr);
43
44/// Returns true if \p VPV is a single scalar, either because it produces the
45/// same value for all lanes or only has its first lane used.
46bool isSingleScalar(const VPValue *VPV);
47
48/// Return true if \p V is a header mask in \p Plan.
49bool isHeaderMask(const VPValue *V, const VPlan &Plan);
50
51/// Checks if \p V is uniform across all VF lanes and UF parts. It is considered
52/// as such if it is either loop invariant (defined outside the vector region)
53/// or its operand is known to be uniform across all VFs and UFs (e.g.
54/// VPDerivedIV or VPCanonicalIVPHI).
56
57/// Returns the header block of the first, top-level loop, or null if none
58/// exist.
60
61/// Get the VF scaling factor applied to the recipe's output, if the recipe has
62/// one.
64
65/// Returns the VPValue representing the uncountable exit comparison used by
66/// AnyOf if the recipes it depends on can be traced back to live-ins and
67/// the addresses (in GEP/PtrAdd form) of any (non-masked) load used in
68/// generating the values for the comparison. The recipes are stored in
69/// \p Recipes, and recipes forming an address for a load are also added to
70/// \p GEPs.
72std::optional<VPValue *>
76} // namespace vputils
77
78//===----------------------------------------------------------------------===//
79// Utilities for modifying predecessors and successors of VPlan blocks.
80//===----------------------------------------------------------------------===//
81
82/// Class that provides utilities for VPBlockBases in VPlan.
84public:
85 VPBlockUtils() = delete;
86
87 /// Insert disconnected VPBlockBase \p NewBlock after \p BlockPtr. Add \p
88 /// NewBlock as successor of \p BlockPtr and \p BlockPtr as predecessor of \p
89 /// NewBlock, and propagate \p BlockPtr parent to \p NewBlock. \p BlockPtr's
90 /// successors are moved from \p BlockPtr to \p NewBlock. \p NewBlock must
91 /// have neither successors nor predecessors.
92 static void insertBlockAfter(VPBlockBase *NewBlock, VPBlockBase *BlockPtr) {
93 assert(NewBlock->getSuccessors().empty() &&
94 NewBlock->getPredecessors().empty() &&
95 "Can't insert new block with predecessors or successors.");
96 NewBlock->setParent(BlockPtr->getParent());
97 SmallVector<VPBlockBase *> Succs(BlockPtr->successors());
98 for (VPBlockBase *Succ : Succs) {
99 Succ->replacePredecessor(BlockPtr, NewBlock);
100 NewBlock->appendSuccessor(Succ);
101 }
102 BlockPtr->clearSuccessors();
103 connectBlocks(BlockPtr, NewBlock);
104 }
105
106 /// Insert disconnected block \p NewBlock before \p Blockptr. First
107 /// disconnects all predecessors of \p BlockPtr and connects them to \p
108 /// NewBlock. Add \p NewBlock as predecessor of \p BlockPtr and \p BlockPtr as
109 /// successor of \p NewBlock.
110 static void insertBlockBefore(VPBlockBase *NewBlock, VPBlockBase *BlockPtr) {
111 assert(NewBlock->getSuccessors().empty() &&
112 NewBlock->getPredecessors().empty() &&
113 "Can't insert new block with predecessors or successors.");
114 NewBlock->setParent(BlockPtr->getParent());
115 for (VPBlockBase *Pred : to_vector(BlockPtr->predecessors())) {
116 Pred->replaceSuccessor(BlockPtr, NewBlock);
117 NewBlock->appendPredecessor(Pred);
118 }
119 BlockPtr->clearPredecessors();
120 connectBlocks(NewBlock, BlockPtr);
121 }
122
123 /// Insert disconnected VPBlockBases \p IfTrue and \p IfFalse after \p
124 /// BlockPtr. Add \p IfTrue and \p IfFalse as succesors of \p BlockPtr and \p
125 /// BlockPtr as predecessor of \p IfTrue and \p IfFalse. Propagate \p BlockPtr
126 /// parent to \p IfTrue and \p IfFalse. \p BlockPtr must have no successors
127 /// and \p IfTrue and \p IfFalse must have neither successors nor
128 /// predecessors.
129 static void insertTwoBlocksAfter(VPBlockBase *IfTrue, VPBlockBase *IfFalse,
130 VPBlockBase *BlockPtr) {
131 assert(IfTrue->getSuccessors().empty() &&
132 "Can't insert IfTrue with successors.");
133 assert(IfFalse->getSuccessors().empty() &&
134 "Can't insert IfFalse with successors.");
135 BlockPtr->setTwoSuccessors(IfTrue, IfFalse);
136 IfTrue->setPredecessors({BlockPtr});
137 IfFalse->setPredecessors({BlockPtr});
138 IfTrue->setParent(BlockPtr->getParent());
139 IfFalse->setParent(BlockPtr->getParent());
140 }
141
142 /// Connect VPBlockBases \p From and \p To bi-directionally. If \p PredIdx is
143 /// -1, append \p From to the predecessors of \p To, otherwise set \p To's
144 /// predecessor at \p PredIdx to \p From. If \p SuccIdx is -1, append \p To to
145 /// the successors of \p From, otherwise set \p From's successor at \p SuccIdx
146 /// to \p To. Both VPBlockBases must have the same parent, which can be null.
147 /// Both VPBlockBases can be already connected to other VPBlockBases.
148 static void connectBlocks(VPBlockBase *From, VPBlockBase *To,
149 unsigned PredIdx = -1u, unsigned SuccIdx = -1u) {
150 assert((From->getParent() == To->getParent()) &&
151 "Can't connect two block with different parents");
152 assert((SuccIdx != -1u || From->getNumSuccessors() < 2) &&
153 "Blocks can't have more than two successors.");
154 if (SuccIdx == -1u)
155 From->appendSuccessor(To);
156 else
157 From->getSuccessors()[SuccIdx] = To;
158
159 if (PredIdx == -1u)
160 To->appendPredecessor(From);
161 else
162 To->getPredecessors()[PredIdx] = From;
163 }
164
165 /// Disconnect VPBlockBases \p From and \p To bi-directionally. Remove \p To
166 /// from the successors of \p From and \p From from the predecessors of \p To.
167 static void disconnectBlocks(VPBlockBase *From, VPBlockBase *To) {
168 assert(To && "Successor to disconnect is null.");
169 From->removeSuccessor(To);
170 To->removePredecessor(From);
171 }
172
173 /// Reassociate all the blocks connected to \p Old so that they now point to
174 /// \p New.
175 static void reassociateBlocks(VPBlockBase *Old, VPBlockBase *New) {
176 for (auto *Pred : to_vector(Old->getPredecessors()))
177 Pred->replaceSuccessor(Old, New);
178 for (auto *Succ : to_vector(Old->getSuccessors()))
179 Succ->replacePredecessor(Old, New);
180 New->setPredecessors(Old->getPredecessors());
181 New->setSuccessors(Old->getSuccessors());
182 Old->clearPredecessors();
183 Old->clearSuccessors();
184 }
185
186 /// Return an iterator range over \p Range which only includes \p BlockTy
187 /// blocks. The accesses are casted to \p BlockTy.
188 template <typename BlockTy, typename T>
189 static auto blocksOnly(const T &Range) {
190 // Create BaseTy with correct const-ness based on BlockTy.
191 using BaseTy = std::conditional_t<std::is_const<BlockTy>::value,
192 const VPBlockBase, VPBlockBase>;
193
194 // We need to first create an iterator range over (const) BlocktTy & instead
195 // of (const) BlockTy * for filter_range to work properly.
196 auto Mapped =
197 map_range(Range, [](BaseTy *Block) -> BaseTy & { return *Block; });
199 Mapped, [](BaseTy &Block) { return isa<BlockTy>(&Block); });
200 return map_range(Filter, [](BaseTy &Block) -> BlockTy * {
201 return cast<BlockTy>(&Block);
202 });
203 }
204
205 /// Inserts \p BlockPtr on the edge between \p From and \p To. That is, update
206 /// \p From's successor to \p To to point to \p BlockPtr and \p To's
207 /// predecessor from \p From to \p BlockPtr. \p From and \p To are added to \p
208 /// BlockPtr's predecessors and successors respectively. There must be a
209 /// single edge between \p From and \p To.
210 static void insertOnEdge(VPBlockBase *From, VPBlockBase *To,
211 VPBlockBase *BlockPtr) {
212 unsigned SuccIdx = From->getIndexForSuccessor(To);
213 unsigned PredIx = To->getIndexForPredecessor(From);
214 VPBlockUtils::connectBlocks(From, BlockPtr, -1, SuccIdx);
215 VPBlockUtils::connectBlocks(BlockPtr, To, PredIx, -1);
216 }
217
218 /// Returns true if \p VPB is a loop header, based on regions or \p VPDT in
219 /// their absence.
220 static bool isHeader(const VPBlockBase *VPB, const VPDominatorTree &VPDT);
221
222 /// Returns true if \p VPB is a loop latch, using isHeader().
223 static bool isLatch(const VPBlockBase *VPB, const VPDominatorTree &VPDT);
224};
225
226} // namespace llvm
227
228#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_ABI_FOR_TEST
Definition Compiler.h:218
std::pair< BasicBlock *, unsigned > BlockTy
A pair of (basic block, score).
#define T
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
This file contains the declarations of the Vectorization Plan base classes:
Represents a single loop in the control flow graph.
Definition LoopInfo.h:40
This class represents an analyzed expression in the program.
The main scalar evolution driver.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
VPBasicBlock serves as the leaf of the Hierarchical Control-Flow Graph.
Definition VPlan.h:3824
VPBlockBase is the building block of the Hierarchical Control-Flow Graph.
Definition VPlan.h:80
VPRegionBlock * getParent()
Definition VPlan.h:172
iterator_range< VPBlockBase ** > predecessors()
Definition VPlan.h:201
size_t getNumSuccessors() const
Definition VPlan.h:218
iterator_range< VPBlockBase ** > successors()
Definition VPlan.h:200
unsigned getIndexForSuccessor(const VPBlockBase *Succ) const
Returns the index for Succ in the blocks successor list.
Definition VPlan.h:334
void setPredecessors(ArrayRef< VPBlockBase * > NewPreds)
Set each VPBasicBlock in NewPreds as predecessor of this VPBlockBase.
Definition VPlan.h:290
unsigned getIndexForPredecessor(const VPBlockBase *Pred) const
Returns the index for Pred in the blocks predecessors list.
Definition VPlan.h:327
const VPBlocksTy & getPredecessors() const
Definition VPlan.h:203
void clearSuccessors()
Remove all the successors of this block.
Definition VPlan.h:309
void setTwoSuccessors(VPBlockBase *IfTrue, VPBlockBase *IfFalse)
Set two given VPBlockBases IfTrue and IfFalse to be the two successors of this VPBlockBase.
Definition VPlan.h:281
void clearPredecessors()
Remove all the predecessor of this block.
Definition VPlan.h:306
void setParent(VPRegionBlock *P)
Definition VPlan.h:183
const VPBlocksTy & getSuccessors() const
Definition VPlan.h:197
static auto blocksOnly(const T &Range)
Return an iterator range over Range which only includes BlockTy blocks.
Definition VPlanUtils.h:189
static void insertBlockAfter(VPBlockBase *NewBlock, VPBlockBase *BlockPtr)
Insert disconnected VPBlockBase NewBlock after BlockPtr.
Definition VPlanUtils.h:92
static void insertOnEdge(VPBlockBase *From, VPBlockBase *To, VPBlockBase *BlockPtr)
Inserts BlockPtr on the edge between From and To.
Definition VPlanUtils.h:210
static bool isLatch(const VPBlockBase *VPB, const VPDominatorTree &VPDT)
Returns true if VPB is a loop latch, using isHeader().
static bool isHeader(const VPBlockBase *VPB, const VPDominatorTree &VPDT)
Returns true if VPB is a loop header, based on regions or VPDT in their absence.
static void insertTwoBlocksAfter(VPBlockBase *IfTrue, VPBlockBase *IfFalse, VPBlockBase *BlockPtr)
Insert disconnected VPBlockBases IfTrue and IfFalse after BlockPtr.
Definition VPlanUtils.h:129
static void connectBlocks(VPBlockBase *From, VPBlockBase *To, unsigned PredIdx=-1u, unsigned SuccIdx=-1u)
Connect VPBlockBases From and To bi-directionally.
Definition VPlanUtils.h:148
static void disconnectBlocks(VPBlockBase *From, VPBlockBase *To)
Disconnect VPBlockBases From and To bi-directionally.
Definition VPlanUtils.h:167
static void reassociateBlocks(VPBlockBase *Old, VPBlockBase *New)
Reassociate all the blocks connected to Old so that they now point to New.
Definition VPlanUtils.h:175
static void insertBlockBefore(VPBlockBase *NewBlock, VPBlockBase *BlockPtr)
Insert disconnected block NewBlock before Blockptr.
Definition VPlanUtils.h:110
Template specialization of the standard LLVM dominator tree utility for VPBlockBases.
VPRecipeBase is a base class modeling a sequence of one or more output IR instructions.
Definition VPlan.h:386
This is the base class of the VPlan Def/Use graph, used for modeling the data flow into,...
Definition VPlanValue.h:48
VPlan models a candidate for vectorization, encoding various decisions take to produce efficient outp...
Definition VPlan.h:4142
bool isSingleScalar(const VPValue *VPV)
Returns true if VPV is a single scalar, either because it produces the same value for all lanes or on...
bool isUniformAcrossVFsAndUFs(VPValue *V)
Checks if V is uniform across all VF lanes and UF parts.
VPValue * getOrCreateVPValueForSCEVExpr(VPlan &Plan, const SCEV *Expr)
Get or create a VPValue that corresponds to the expansion of Expr.
VPBasicBlock * getFirstLoopHeader(VPlan &Plan, VPDominatorTree &VPDT)
Returns the header block of the first, top-level loop, or null if none exist.
bool onlyFirstPartUsed(const VPValue *Def)
Returns true if only the first part of Def is used.
bool onlyFirstLaneUsed(const VPValue *Def)
Returns true if only the first lane of Def is used.
bool onlyScalarValuesUsed(const VPValue *Def)
Returns true if only scalar values of Def are used by all users.
unsigned getVFScaleFactor(VPRecipeBase *R)
Get the VF scaling factor applied to the recipe's output, if the recipe has one.
bool isHeaderMask(const VPValue *V, const VPlan &Plan)
Return true if V is a header mask in Plan.
LLVM_ABI_FOR_TEST std::optional< VPValue * > getRecipesForUncountableExit(VPlan &Plan, SmallVectorImpl< VPRecipeBase * > &Recipes, SmallVectorImpl< VPRecipeBase * > &GEPs)
Returns the VPValue representing the uncountable exit comparison used by AnyOf if the recipes it depe...
const SCEV * getSCEVExprForVPValue(const VPValue *V, ScalarEvolution &SE, const Loop *L=nullptr)
Return the SCEV expression for V.
This is an optimization pass for GlobalISel generic memory operations.
auto map_range(ContainerTy &&C, FuncTy F)
Definition STLExtras.h:364
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
Definition STLExtras.h:550
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559