LLVM 20.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/// Get or create a VPValue that corresponds to the expansion of \p Expr. If \p
29/// Expr is a SCEVConstant or SCEVUnknown, return a VPValue wrapping the live-in
30/// value. Otherwise return a VPExpandSCEVRecipe to expand \p Expr. If \p Plan's
31/// pre-header already contains a recipe expanding \p Expr, return it. If not,
32/// create a new one.
34 ScalarEvolution &SE);
35
36/// Return the SCEV expression for \p V. Returns SCEVCouldNotCompute if no
37/// SCEV expression could be constructed.
39
40/// Returns true if \p VPV is uniform after vectorization.
41inline bool isUniformAfterVectorization(const VPValue *VPV) {
42 // A value defined outside the vector region must be uniform after
43 // vectorization inside a vector region.
45 return true;
46 if (auto *Rep = dyn_cast<VPReplicateRecipe>(VPV))
47 return Rep->isUniform();
48 if (isa<VPWidenGEPRecipe, VPDerivedIVRecipe>(VPV))
49 return all_of(VPV->getDefiningRecipe()->operands(),
51 if (auto *VPI = dyn_cast<VPInstruction>(VPV))
52 return VPI->isSingleScalar() || VPI->isVectorToScalar() ||
53 ((Instruction::isBinaryOp(VPI->getOpcode()) ||
54 VPI->getOpcode() == VPInstruction::PtrAdd) &&
55 all_of(VPI->operands(), isUniformAfterVectorization));
56 if (auto *IV = dyn_cast<VPDerivedIVRecipe>(VPV))
57 return all_of(IV->operands(), isUniformAfterVectorization);
58
59 // VPExpandSCEVRecipes must be placed in the entry and are alway uniform.
60 return isa<VPExpandSCEVRecipe>(VPV);
61}
62
63/// Return true if \p V is a header mask in \p Plan.
64bool isHeaderMask(const VPValue *V, VPlan &Plan);
65
66/// Checks if \p V is uniform across all VF lanes and UF parts. It is considered
67/// as such if it is either loop invariant (defined outside the vector region)
68/// or its operand is known to be uniform across all VFs and UFs (e.g.
69/// VPDerivedIV or VPCanonicalIVPHI).
71
72} // namespace vputils
73
74//===----------------------------------------------------------------------===//
75// Utilities for modifying predecessors and successors of VPlan blocks.
76//===----------------------------------------------------------------------===//
77
78/// Class that provides utilities for VPBlockBases in VPlan.
80public:
81 VPBlockUtils() = delete;
82
83 /// Insert disconnected VPBlockBase \p NewBlock after \p BlockPtr. Add \p
84 /// NewBlock as successor of \p BlockPtr and \p BlockPtr as predecessor of \p
85 /// NewBlock, and propagate \p BlockPtr parent to \p NewBlock. \p BlockPtr's
86 /// successors are moved from \p BlockPtr to \p NewBlock. \p NewBlock must
87 /// have neither successors nor predecessors.
88 static void insertBlockAfter(VPBlockBase *NewBlock, VPBlockBase *BlockPtr) {
89 assert(NewBlock->getSuccessors().empty() &&
90 NewBlock->getPredecessors().empty() &&
91 "Can't insert new block with predecessors or successors.");
92 NewBlock->setParent(BlockPtr->getParent());
93 SmallVector<VPBlockBase *> Succs(BlockPtr->successors());
94 for (VPBlockBase *Succ : Succs) {
95 disconnectBlocks(BlockPtr, Succ);
96 connectBlocks(NewBlock, Succ);
97 }
98 connectBlocks(BlockPtr, NewBlock);
99 }
100
101 /// Insert disconnected block \p NewBlock before \p Blockptr. First
102 /// disconnects all predecessors of \p BlockPtr and connects them to \p
103 /// NewBlock. Add \p NewBlock as predecessor of \p BlockPtr and \p BlockPtr as
104 /// successor of \p NewBlock.
105 static void insertBlockBefore(VPBlockBase *NewBlock, VPBlockBase *BlockPtr) {
106 assert(NewBlock->getSuccessors().empty() &&
107 NewBlock->getPredecessors().empty() &&
108 "Can't insert new block with predecessors or successors.");
109 NewBlock->setParent(BlockPtr->getParent());
110 for (VPBlockBase *Pred : to_vector(BlockPtr->predecessors())) {
111 disconnectBlocks(Pred, BlockPtr);
112 connectBlocks(Pred, NewBlock);
113 }
114 connectBlocks(NewBlock, BlockPtr);
115 }
116
117 /// Insert disconnected VPBlockBases \p IfTrue and \p IfFalse after \p
118 /// BlockPtr. Add \p IfTrue and \p IfFalse as succesors of \p BlockPtr and \p
119 /// BlockPtr as predecessor of \p IfTrue and \p IfFalse. Propagate \p BlockPtr
120 /// parent to \p IfTrue and \p IfFalse. \p BlockPtr must have no successors
121 /// and \p IfTrue and \p IfFalse must have neither successors nor
122 /// predecessors.
123 static void insertTwoBlocksAfter(VPBlockBase *IfTrue, VPBlockBase *IfFalse,
124 VPBlockBase *BlockPtr) {
125 assert(IfTrue->getSuccessors().empty() &&
126 "Can't insert IfTrue with successors.");
127 assert(IfFalse->getSuccessors().empty() &&
128 "Can't insert IfFalse with successors.");
129 BlockPtr->setTwoSuccessors(IfTrue, IfFalse);
130 IfTrue->setPredecessors({BlockPtr});
131 IfFalse->setPredecessors({BlockPtr});
132 IfTrue->setParent(BlockPtr->getParent());
133 IfFalse->setParent(BlockPtr->getParent());
134 }
135
136 /// Connect VPBlockBases \p From and \p To bi-directionally. If \p PredIdx is
137 /// -1, append \p From to the predecessors of \p To, otherwise set \p To's
138 /// predecessor at \p PredIdx to \p From. If \p SuccIdx is -1, append \p To to
139 /// the successors of \p From, otherwise set \p From's successor at \p SuccIdx
140 /// to \p To. Both VPBlockBases must have the same parent, which can be null.
141 /// Both VPBlockBases can be already connected to other VPBlockBases.
143 unsigned PredIdx = -1u, unsigned SuccIdx = -1u) {
144 assert((From->getParent() == To->getParent()) &&
145 "Can't connect two block with different parents");
146 assert((SuccIdx != -1u || From->getNumSuccessors() < 2) &&
147 "Blocks can't have more than two successors.");
148 if (SuccIdx == -1u)
149 From->appendSuccessor(To);
150 else
151 From->getSuccessors()[SuccIdx] = To;
152
153 if (PredIdx == -1u)
154 To->appendPredecessor(From);
155 else
156 To->getPredecessors()[PredIdx] = From;
157 }
158
159 /// Disconnect VPBlockBases \p From and \p To bi-directionally. Remove \p To
160 /// from the successors of \p From and \p From from the predecessors of \p To.
162 assert(To && "Successor to disconnect is null.");
163 From->removeSuccessor(To);
164 To->removePredecessor(From);
165 }
166
167 /// Reassociate all the blocks connected to \p Old so that they now point to
168 /// \p New.
169 static void reassociateBlocks(VPBlockBase *Old, VPBlockBase *New) {
170 for (auto *Pred : to_vector(Old->getPredecessors()))
171 Pred->replaceSuccessor(Old, New);
172 for (auto *Succ : to_vector(Old->getSuccessors()))
173 Succ->replacePredecessor(Old, New);
174 New->setPredecessors(Old->getPredecessors());
175 New->setSuccessors(Old->getSuccessors());
176 Old->clearPredecessors();
177 Old->clearSuccessors();
178 }
179
180 /// Return an iterator range over \p Range which only includes \p BlockTy
181 /// blocks. The accesses are casted to \p BlockTy.
182 template <typename BlockTy, typename T>
183 static auto blocksOnly(const T &Range) {
184 // Create BaseTy with correct const-ness based on BlockTy.
185 using BaseTy = std::conditional_t<std::is_const<BlockTy>::value,
186 const VPBlockBase, VPBlockBase>;
187
188 // We need to first create an iterator range over (const) BlocktTy & instead
189 // of (const) BlockTy * for filter_range to work properly.
190 auto Mapped =
191 map_range(Range, [](BaseTy *Block) -> BaseTy & { return *Block; });
193 Mapped, [](BaseTy &Block) { return isa<BlockTy>(&Block); });
194 return map_range(Filter, [](BaseTy &Block) -> BlockTy * {
195 return cast<BlockTy>(&Block);
196 });
197 }
198
199 /// Inserts \p BlockPtr on the edge between \p From and \p To. That is, update
200 /// \p From's successor to \p To to point to \p BlockPtr and \p To's
201 /// predecessor from \p From to \p BlockPtr. \p From and \p To are added to \p
202 /// BlockPtr's predecessors and successors respectively. There must be a
203 /// single edge between \p From and \p To.
205 VPBlockBase *BlockPtr) {
206 auto &Successors = From->getSuccessors();
207 auto &Predecessors = To->getPredecessors();
208 assert(count(Successors, To) == 1 && count(Predecessors, From) == 1 &&
209 "must have single between From and To");
210 unsigned SuccIdx = std::distance(Successors.begin(), find(Successors, To));
211 unsigned PredIx =
212 std::distance(Predecessors.begin(), find(Predecessors, From));
213 VPBlockUtils::connectBlocks(From, BlockPtr, -1, SuccIdx);
214 VPBlockUtils::connectBlocks(BlockPtr, To, PredIx, -1);
215 }
216};
217
218} // namespace llvm
219
220#endif
BlockVerifier::State From
std::pair< BasicBlock *, unsigned > BlockTy
A pair of (basic block, score).
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains the declarations of the Vectorization Plan base classes:
static const uint32_t IV[8]
Definition: blake3_impl.h:78
bool isBinaryOp() const
Definition: Instruction.h:296
This class represents an analyzed expression in the program.
The main scalar evolution driver.
bool empty() const
Definition: SmallVector.h:81
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
VPBlockBase is the building block of the Hierarchical Control-Flow Graph.
Definition: VPlan.h:391
VPRegionBlock * getParent()
Definition: VPlan.h:483
iterator_range< VPBlockBase ** > predecessors()
Definition: VPlan.h:512
iterator_range< VPBlockBase ** > successors()
Definition: VPlan.h:511
void setPredecessors(ArrayRef< VPBlockBase * > NewPreds)
Set each VPBasicBlock in NewPreds as predecessor of this VPBlockBase.
Definition: VPlan.h:598
const VPBlocksTy & getPredecessors() const
Definition: VPlan.h:514
void clearSuccessors()
Remove all the successors of this block.
Definition: VPlan.h:617
void setTwoSuccessors(VPBlockBase *IfTrue, VPBlockBase *IfFalse)
Set two given VPBlockBases IfTrue and IfFalse to be the two successors of this VPBlockBase.
Definition: VPlan.h:589
void clearPredecessors()
Remove all the predecessor of this block.
Definition: VPlan.h:614
void setParent(VPRegionBlock *P)
Definition: VPlan.h:494
const VPBlocksTy & getSuccessors() const
Definition: VPlan.h:508
Class that provides utilities for VPBlockBases in VPlan.
Definition: VPlanUtils.h:79
static auto blocksOnly(const T &Range)
Return an iterator range over Range which only includes BlockTy blocks.
Definition: VPlanUtils.h:183
static void insertBlockAfter(VPBlockBase *NewBlock, VPBlockBase *BlockPtr)
Insert disconnected VPBlockBase NewBlock after BlockPtr.
Definition: VPlanUtils.h:88
static void insertOnEdge(VPBlockBase *From, VPBlockBase *To, VPBlockBase *BlockPtr)
Inserts BlockPtr on the edge between From and To.
Definition: VPlanUtils.h:204
static void insertTwoBlocksAfter(VPBlockBase *IfTrue, VPBlockBase *IfFalse, VPBlockBase *BlockPtr)
Insert disconnected VPBlockBases IfTrue and IfFalse after BlockPtr.
Definition: VPlanUtils.h:123
static void connectBlocks(VPBlockBase *From, VPBlockBase *To, unsigned PredIdx=-1u, unsigned SuccIdx=-1u)
Connect VPBlockBases From and To bi-directionally.
Definition: VPlanUtils.h:142
static void disconnectBlocks(VPBlockBase *From, VPBlockBase *To)
Disconnect VPBlockBases From and To bi-directionally.
Definition: VPlanUtils.h:161
static void reassociateBlocks(VPBlockBase *Old, VPBlockBase *New)
Reassociate all the blocks connected to Old so that they now point to New.
Definition: VPlanUtils.h:169
static void insertBlockBefore(VPBlockBase *NewBlock, VPBlockBase *BlockPtr)
Insert disconnected block NewBlock before Blockptr.
Definition: VPlanUtils.h:105
operand_range operands()
Definition: VPlanValue.h:263
bool isDefinedOutsideLoopRegions() const
Returns true if the VPValue is defined outside any loop region.
Definition: VPlan.cpp:1417
VPRecipeBase * getDefiningRecipe()
Returns the recipe defining this VPValue or nullptr if it is not defined by a recipe,...
Definition: VPlan.cpp:123
VPlan models a candidate for vectorization, encoding various decisions take to produce efficient outp...
Definition: VPlan.h:3808
bool isUniformAfterVectorization(const VPValue *VPV)
Returns true if VPV is uniform after vectorization.
Definition: VPlanUtils.h:41
VPValue * getOrCreateVPValueForSCEVExpr(VPlan &Plan, const SCEV *Expr, ScalarEvolution &SE)
Get or create a VPValue that corresponds to the expansion of Expr.
Definition: VPlanUtils.cpp:26
bool isUniformAcrossVFsAndUFs(VPValue *V)
Checks if V is uniform across all VF lanes and UF parts.
Definition: VPlanUtils.cpp:76
bool onlyFirstPartUsed(const VPValue *Def)
Returns true if only the first part of Def is used.
Definition: VPlanUtils.cpp:21
const SCEV * getSCEVExprForVPValue(VPValue *V, ScalarEvolution &SE)
Return the SCEV expression for V.
Definition: VPlanUtils.cpp:65
bool onlyFirstLaneUsed(const VPValue *Def)
Returns true if only the first lane of Def is used.
Definition: VPlanUtils.cpp:16
bool isHeaderMask(const VPValue *V, VPlan &Plan)
Return true if V is a header mask in Plan.
Definition: VPlanUtils.cpp:43
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1759
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:1739
auto map_range(ContainerTy &&C, FuncTy F)
Definition: STLExtras.h:377
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:1299
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:573
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
Definition: STLExtras.h:1938