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"
13
14namespace llvm {
15class ScalarEvolution;
16class SCEV;
17} // namespace llvm
18
19namespace llvm {
20
21namespace vputils {
22/// Returns true if only the first lane of \p Def is used.
23bool onlyFirstLaneUsed(const VPValue *Def);
24
25/// Returns true if only the first part of \p Def is used.
26bool onlyFirstPartUsed(const VPValue *Def);
27
28/// Returns true if only scalar values of \p Def are used by all users.
29bool onlyScalarValuesUsed(const VPValue *Def);
30
31/// Get or create a VPValue that corresponds to the expansion of \p Expr. If \p
32/// Expr is a SCEVConstant or SCEVUnknown, return a VPValue wrapping the live-in
33/// value. Otherwise return a VPExpandSCEVRecipe to expand \p Expr. If \p Plan's
34/// pre-header already contains a recipe expanding \p Expr, return it. If not,
35/// create a new one.
37
38/// Return the SCEV expression for \p V. Returns SCEVCouldNotCompute if no
39/// SCEV expression could be constructed.
41
42/// Returns true if \p VPV is a single scalar, either because it produces the
43/// same value for all lanes or only has its first lane used.
44inline bool isSingleScalar(const VPValue *VPV) {
45 auto PreservesUniformity = [](unsigned Opcode) -> bool {
46 if (Instruction::isBinaryOp(Opcode) || Instruction::isCast(Opcode))
47 return true;
48 switch (Opcode) {
49 case Instruction::GetElementPtr:
50 case Instruction::ICmp:
51 case Instruction::FCmp:
52 case Instruction::Select:
55 return true;
56 default:
57 return false;
58 }
59 };
60
61 // A live-in must be uniform across the scope of VPlan.
62 if (VPV->isLiveIn())
63 return true;
64
65 if (auto *Rep = dyn_cast<VPReplicateRecipe>(VPV)) {
66 const VPRegionBlock *RegionOfR = Rep->getParent()->getParent();
67 // Don't consider recipes in replicate regions as uniform yet; their first
68 // lane cannot be accessed when executing the replicate region for other
69 // lanes.
70 if (RegionOfR && RegionOfR->isReplicator())
71 return false;
72 return Rep->isSingleScalar() || (PreservesUniformity(Rep->getOpcode()) &&
73 all_of(Rep->operands(), isSingleScalar));
74 }
78 if (auto *WidenR = dyn_cast<VPWidenRecipe>(VPV)) {
79 return PreservesUniformity(WidenR->getOpcode()) &&
80 all_of(WidenR->operands(), isSingleScalar);
81 }
82 if (auto *VPI = dyn_cast<VPInstruction>(VPV))
83 return VPI->isSingleScalar() || VPI->isVectorToScalar() ||
84 (PreservesUniformity(VPI->getOpcode()) &&
85 all_of(VPI->operands(), isSingleScalar));
86
87 // VPExpandSCEVRecipes must be placed in the entry and are alway uniform.
88 return isa<VPExpandSCEVRecipe>(VPV);
89}
90
91/// Return true if \p V is a header mask in \p Plan.
92bool isHeaderMask(const VPValue *V, VPlan &Plan);
93
94/// Checks if \p V is uniform across all VF lanes and UF parts. It is considered
95/// as such if it is either loop invariant (defined outside the vector region)
96/// or its operand is known to be uniform across all VFs and UFs (e.g.
97/// VPDerivedIV or VPCanonicalIVPHI).
99
100/// Returns the header block of the first, top-level loop, or null if none
101/// exist.
103} // namespace vputils
104
105//===----------------------------------------------------------------------===//
106// Utilities for modifying predecessors and successors of VPlan blocks.
107//===----------------------------------------------------------------------===//
108
109/// Class that provides utilities for VPBlockBases in VPlan.
111public:
112 VPBlockUtils() = delete;
113
114 /// Insert disconnected VPBlockBase \p NewBlock after \p BlockPtr. Add \p
115 /// NewBlock as successor of \p BlockPtr and \p BlockPtr as predecessor of \p
116 /// NewBlock, and propagate \p BlockPtr parent to \p NewBlock. \p BlockPtr's
117 /// successors are moved from \p BlockPtr to \p NewBlock. \p NewBlock must
118 /// have neither successors nor predecessors.
119 static void insertBlockAfter(VPBlockBase *NewBlock, VPBlockBase *BlockPtr) {
120 assert(NewBlock->getSuccessors().empty() &&
121 NewBlock->getPredecessors().empty() &&
122 "Can't insert new block with predecessors or successors.");
123 NewBlock->setParent(BlockPtr->getParent());
124 SmallVector<VPBlockBase *> Succs(BlockPtr->successors());
125 for (VPBlockBase *Succ : Succs) {
126 Succ->replacePredecessor(BlockPtr, NewBlock);
127 NewBlock->appendSuccessor(Succ);
128 }
129 BlockPtr->clearSuccessors();
130 connectBlocks(BlockPtr, NewBlock);
131 }
132
133 /// Insert disconnected block \p NewBlock before \p Blockptr. First
134 /// disconnects all predecessors of \p BlockPtr and connects them to \p
135 /// NewBlock. Add \p NewBlock as predecessor of \p BlockPtr and \p BlockPtr as
136 /// successor of \p NewBlock.
137 static void insertBlockBefore(VPBlockBase *NewBlock, VPBlockBase *BlockPtr) {
138 assert(NewBlock->getSuccessors().empty() &&
139 NewBlock->getPredecessors().empty() &&
140 "Can't insert new block with predecessors or successors.");
141 NewBlock->setParent(BlockPtr->getParent());
142 for (VPBlockBase *Pred : to_vector(BlockPtr->predecessors())) {
143 Pred->replaceSuccessor(BlockPtr, NewBlock);
144 NewBlock->appendPredecessor(Pred);
145 }
146 BlockPtr->clearPredecessors();
147 connectBlocks(NewBlock, BlockPtr);
148 }
149
150 /// Insert disconnected VPBlockBases \p IfTrue and \p IfFalse after \p
151 /// BlockPtr. Add \p IfTrue and \p IfFalse as succesors of \p BlockPtr and \p
152 /// BlockPtr as predecessor of \p IfTrue and \p IfFalse. Propagate \p BlockPtr
153 /// parent to \p IfTrue and \p IfFalse. \p BlockPtr must have no successors
154 /// and \p IfTrue and \p IfFalse must have neither successors nor
155 /// predecessors.
156 static void insertTwoBlocksAfter(VPBlockBase *IfTrue, VPBlockBase *IfFalse,
157 VPBlockBase *BlockPtr) {
158 assert(IfTrue->getSuccessors().empty() &&
159 "Can't insert IfTrue with successors.");
160 assert(IfFalse->getSuccessors().empty() &&
161 "Can't insert IfFalse with successors.");
162 BlockPtr->setTwoSuccessors(IfTrue, IfFalse);
163 IfTrue->setPredecessors({BlockPtr});
164 IfFalse->setPredecessors({BlockPtr});
165 IfTrue->setParent(BlockPtr->getParent());
166 IfFalse->setParent(BlockPtr->getParent());
167 }
168
169 /// Connect VPBlockBases \p From and \p To bi-directionally. If \p PredIdx is
170 /// -1, append \p From to the predecessors of \p To, otherwise set \p To's
171 /// predecessor at \p PredIdx to \p From. If \p SuccIdx is -1, append \p To to
172 /// the successors of \p From, otherwise set \p From's successor at \p SuccIdx
173 /// to \p To. Both VPBlockBases must have the same parent, which can be null.
174 /// Both VPBlockBases can be already connected to other VPBlockBases.
176 unsigned PredIdx = -1u, unsigned SuccIdx = -1u) {
177 assert((From->getParent() == To->getParent()) &&
178 "Can't connect two block with different parents");
179 assert((SuccIdx != -1u || From->getNumSuccessors() < 2) &&
180 "Blocks can't have more than two successors.");
181 if (SuccIdx == -1u)
182 From->appendSuccessor(To);
183 else
184 From->getSuccessors()[SuccIdx] = To;
185
186 if (PredIdx == -1u)
187 To->appendPredecessor(From);
188 else
189 To->getPredecessors()[PredIdx] = From;
190 }
191
192 /// Disconnect VPBlockBases \p From and \p To bi-directionally. Remove \p To
193 /// from the successors of \p From and \p From from the predecessors of \p To.
195 assert(To && "Successor to disconnect is null.");
196 From->removeSuccessor(To);
197 To->removePredecessor(From);
198 }
199
200 /// Reassociate all the blocks connected to \p Old so that they now point to
201 /// \p New.
202 static void reassociateBlocks(VPBlockBase *Old, VPBlockBase *New) {
203 for (auto *Pred : to_vector(Old->getPredecessors()))
204 Pred->replaceSuccessor(Old, New);
205 for (auto *Succ : to_vector(Old->getSuccessors()))
206 Succ->replacePredecessor(Old, New);
207 New->setPredecessors(Old->getPredecessors());
208 New->setSuccessors(Old->getSuccessors());
209 Old->clearPredecessors();
210 Old->clearSuccessors();
211 }
212
213 /// Return an iterator range over \p Range which only includes \p BlockTy
214 /// blocks. The accesses are casted to \p BlockTy.
215 template <typename BlockTy, typename T>
216 static auto blocksOnly(const T &Range) {
217 // Create BaseTy with correct const-ness based on BlockTy.
218 using BaseTy = std::conditional_t<std::is_const<BlockTy>::value,
219 const VPBlockBase, VPBlockBase>;
220
221 // We need to first create an iterator range over (const) BlocktTy & instead
222 // of (const) BlockTy * for filter_range to work properly.
223 auto Mapped =
224 map_range(Range, [](BaseTy *Block) -> BaseTy & { return *Block; });
226 Mapped, [](BaseTy &Block) { return isa<BlockTy>(&Block); });
227 return map_range(Filter, [](BaseTy &Block) -> BlockTy * {
228 return cast<BlockTy>(&Block);
229 });
230 }
231
232 /// Inserts \p BlockPtr on the edge between \p From and \p To. That is, update
233 /// \p From's successor to \p To to point to \p BlockPtr and \p To's
234 /// predecessor from \p From to \p BlockPtr. \p From and \p To are added to \p
235 /// BlockPtr's predecessors and successors respectively. There must be a
236 /// single edge between \p From and \p To.
238 VPBlockBase *BlockPtr) {
239 unsigned SuccIdx = From->getIndexForSuccessor(To);
240 unsigned PredIx = To->getIndexForPredecessor(From);
241 VPBlockUtils::connectBlocks(From, BlockPtr, -1, SuccIdx);
242 VPBlockUtils::connectBlocks(BlockPtr, To, PredIx, -1);
243 }
244
245 /// Returns true if \p VPB is a loop header, based on regions or \p VPDT in
246 /// their absence.
247 static bool isHeader(const VPBlockBase *VPB, const VPDominatorTree &VPDT);
248
249 /// Returns true if \p VPB is a loop latch, using isHeader().
250 static bool isLatch(const VPBlockBase *VPB, const VPDominatorTree &VPDT);
251};
252
253} // namespace llvm
254
255#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
BlockVerifier::State From
std::pair< BasicBlock *, unsigned > BlockTy
A pair of (basic block, score).
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
This file contains the declarations of the Vectorization Plan base classes:
bool isCast() const
Definition: Instruction.h:321
bool isBinaryOp() const
Definition: Instruction.h:317
This class represents an analyzed expression in the program.
The main scalar evolution driver.
bool empty() const
Definition: SmallVector.h:82
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
VPBasicBlock serves as the leaf of the Hierarchical Control-Flow Graph.
Definition: VPlan.h:3639
A recipe for vectorizing a phi-node as a sequence of mask-based select instructions.
Definition: VPlan.h:2374
VPBlockBase is the building block of the Hierarchical Control-Flow Graph.
Definition: VPlan.h:81
VPRegionBlock * getParent()
Definition: VPlan.h:173
iterator_range< VPBlockBase ** > predecessors()
Definition: VPlan.h:202
iterator_range< VPBlockBase ** > successors()
Definition: VPlan.h:201
void setPredecessors(ArrayRef< VPBlockBase * > NewPreds)
Set each VPBasicBlock in NewPreds as predecessor of this VPBlockBase.
Definition: VPlan.h:288
unsigned getIndexForPredecessor(const VPBlockBase *Pred) const
Returns the index for Pred in the blocks predecessors list.
Definition: VPlan.h:325
const VPBlocksTy & getPredecessors() const
Definition: VPlan.h:204
void clearSuccessors()
Remove all the successors of this block.
Definition: VPlan.h:307
void setTwoSuccessors(VPBlockBase *IfTrue, VPBlockBase *IfFalse)
Set two given VPBlockBases IfTrue and IfFalse to be the two successors of this VPBlockBase.
Definition: VPlan.h:279
void clearPredecessors()
Remove all the predecessor of this block.
Definition: VPlan.h:304
void setParent(VPRegionBlock *P)
Definition: VPlan.h:184
const VPBlocksTy & getSuccessors() const
Definition: VPlan.h:198
Class that provides utilities for VPBlockBases in VPlan.
Definition: VPlanUtils.h:110
static auto blocksOnly(const T &Range)
Return an iterator range over Range which only includes BlockTy blocks.
Definition: VPlanUtils.h:216
static void insertBlockAfter(VPBlockBase *NewBlock, VPBlockBase *BlockPtr)
Insert disconnected VPBlockBase NewBlock after BlockPtr.
Definition: VPlanUtils.h:119
static void insertOnEdge(VPBlockBase *From, VPBlockBase *To, VPBlockBase *BlockPtr)
Inserts BlockPtr on the edge between From and To.
Definition: VPlanUtils.h:237
static bool isLatch(const VPBlockBase *VPB, const VPDominatorTree &VPDT)
Returns true if VPB is a loop latch, using isHeader().
Definition: VPlan.cpp:227
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.
Definition: VPlan.cpp:210
static void insertTwoBlocksAfter(VPBlockBase *IfTrue, VPBlockBase *IfFalse, VPBlockBase *BlockPtr)
Insert disconnected VPBlockBases IfTrue and IfFalse after BlockPtr.
Definition: VPlanUtils.h:156
static void connectBlocks(VPBlockBase *From, VPBlockBase *To, unsigned PredIdx=-1u, unsigned SuccIdx=-1u)
Connect VPBlockBases From and To bi-directionally.
Definition: VPlanUtils.h:175
static void disconnectBlocks(VPBlockBase *From, VPBlockBase *To)
Disconnect VPBlockBases From and To bi-directionally.
Definition: VPlanUtils.h:194
static void reassociateBlocks(VPBlockBase *Old, VPBlockBase *New)
Reassociate all the blocks connected to Old so that they now point to New.
Definition: VPlanUtils.h:202
static void insertBlockBefore(VPBlockBase *NewBlock, VPBlockBase *BlockPtr)
Insert disconnected block NewBlock before Blockptr.
Definition: VPlanUtils.h:137
A recipe for converting the input value IV value to the corresponding value of an IV with different s...
Definition: VPlan.h:3460
Template specialization of the standard LLVM dominator tree utility for VPBlockBases.
VPRegionBlock represents a collection of VPBasicBlocks and VPRegionBlocks which form a Single-Entry-S...
Definition: VPlan.h:3827
bool isReplicator() const
An indicator whether this region is to generate multiple replicated instances of output IR correspond...
Definition: VPlan.h:3895
operand_range operands()
Definition: VPlanValue.h:265
VPRecipeBase * getDefiningRecipe()
Returns the recipe defining this VPValue or nullptr if it is not defined by a recipe,...
Definition: VPlan.cpp:125
bool isLiveIn() const
Returns true if this VPValue is a live-in, i.e. defined outside the VPlan.
Definition: VPlanValue.h:169
A recipe for handling GEP instructions.
Definition: VPlan.h:1753
VPlan models a candidate for vectorization, encoding various decisions take to produce efficient outp...
Definition: VPlan.h:3930
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...
Definition: VPlanUtils.h:44
bool isUniformAcrossVFsAndUFs(VPValue *V)
Checks if V is uniform across all VF lanes and UF parts.
Definition: VPlanUtils.cpp:93
VPValue * getOrCreateVPValueForSCEVExpr(VPlan &Plan, const SCEV *Expr)
Get or create a VPValue that corresponds to the expansion of Expr.
Definition: VPlanUtils.cpp:32
VPBasicBlock * getFirstLoopHeader(VPlan &Plan, VPDominatorTree &VPDT)
Returns the header block of the first, top-level loop, or null if none exist.
Definition: VPlanUtils.cpp:138
bool onlyFirstPartUsed(const VPValue *Def)
Returns true if only the first part of Def is used.
Definition: VPlanUtils.cpp:22
const SCEV * getSCEVExprForVPValue(VPValue *V, ScalarEvolution &SE)
Return the SCEV expression for V.
Definition: VPlanUtils.cpp:79
bool onlyFirstLaneUsed(const VPValue *Def)
Returns true if only the first lane of Def is used.
Definition: VPlanUtils.cpp:17
bool isHeaderMask(const VPValue *V, VPlan &Plan)
Return true if V is a header mask in Plan.
Definition: VPlanUtils.cpp:55
bool onlyScalarValuesUsed(const VPValue *Def)
Returns true if only scalar values of Def are used by all users.
Definition: VPlanUtils.cpp:27
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1744
auto map_range(ContainerTy &&C, FuncTy F)
Definition: STLExtras.h:386
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...
Definition: SmallVector.h:1300
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:581
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:548
A recipe for widening select instructions.
Definition: VPlan.h:1707