xref: /llvm-project/llvm/lib/Transforms/Vectorize/VPlanUtils.h (revision 05fbc3830d05878a0521a3e07aa1e469905ce732)
171ede8d8SRamkumar Ramachandra //===- VPlanUtils.h - VPlan-related utilities -------------------*- C++ -*-===//
271ede8d8SRamkumar Ramachandra //
371ede8d8SRamkumar Ramachandra // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
471ede8d8SRamkumar Ramachandra // See https://llvm.org/LICENSE.txt for license information.
571ede8d8SRamkumar Ramachandra // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
671ede8d8SRamkumar Ramachandra //
771ede8d8SRamkumar Ramachandra //===----------------------------------------------------------------------===//
871ede8d8SRamkumar Ramachandra 
971ede8d8SRamkumar Ramachandra #ifndef LLVM_TRANSFORMS_VECTORIZE_VPLANUTILS_H
1071ede8d8SRamkumar Ramachandra #define LLVM_TRANSFORMS_VECTORIZE_VPLANUTILS_H
1171ede8d8SRamkumar Ramachandra 
1271ede8d8SRamkumar Ramachandra #include "VPlan.h"
1371ede8d8SRamkumar Ramachandra 
140d736e29SFlorian Hahn namespace llvm {
150d736e29SFlorian Hahn class ScalarEvolution;
160d736e29SFlorian Hahn class SCEV;
170d736e29SFlorian Hahn } // namespace llvm
180d736e29SFlorian Hahn 
19*05fbc383SFlorian Hahn namespace llvm {
20*05fbc383SFlorian Hahn 
21*05fbc383SFlorian Hahn namespace vputils {
2271ede8d8SRamkumar Ramachandra /// Returns true if only the first lane of \p Def is used.
2371ede8d8SRamkumar Ramachandra bool onlyFirstLaneUsed(const VPValue *Def);
2471ede8d8SRamkumar Ramachandra 
2571ede8d8SRamkumar Ramachandra /// Returns true if only the first part of \p Def is used.
2671ede8d8SRamkumar Ramachandra bool onlyFirstPartUsed(const VPValue *Def);
2771ede8d8SRamkumar Ramachandra 
2871ede8d8SRamkumar Ramachandra /// Get or create a VPValue that corresponds to the expansion of \p Expr. If \p
2971ede8d8SRamkumar Ramachandra /// Expr is a SCEVConstant or SCEVUnknown, return a VPValue wrapping the live-in
3071ede8d8SRamkumar Ramachandra /// value. Otherwise return a VPExpandSCEVRecipe to expand \p Expr. If \p Plan's
3171ede8d8SRamkumar Ramachandra /// pre-header already contains a recipe expanding \p Expr, return it. If not,
3271ede8d8SRamkumar Ramachandra /// create a new one.
3371ede8d8SRamkumar Ramachandra VPValue *getOrCreateVPValueForSCEVExpr(VPlan &Plan, const SCEV *Expr,
3471ede8d8SRamkumar Ramachandra                                        ScalarEvolution &SE);
3571ede8d8SRamkumar Ramachandra 
360d736e29SFlorian Hahn /// Return the SCEV expression for \p V. Returns SCEVCouldNotCompute if no
370d736e29SFlorian Hahn /// SCEV expression could be constructed.
380d736e29SFlorian Hahn const SCEV *getSCEVExprForVPValue(VPValue *V, ScalarEvolution &SE);
390d736e29SFlorian Hahn 
4071ede8d8SRamkumar Ramachandra /// Returns true if \p VPV is uniform after vectorization.
4171ede8d8SRamkumar Ramachandra inline bool isUniformAfterVectorization(const VPValue *VPV) {
4271ede8d8SRamkumar Ramachandra   // A value defined outside the vector region must be uniform after
4371ede8d8SRamkumar Ramachandra   // vectorization inside a vector region.
4425610048SFlorian Hahn   if (VPV->isDefinedOutsideLoopRegions())
4571ede8d8SRamkumar Ramachandra     return true;
46bd5e12e6SFlorian Hahn   if (auto *Rep = dyn_cast<VPReplicateRecipe>(VPV))
4771ede8d8SRamkumar Ramachandra     return Rep->isUniform();
48bd5e12e6SFlorian Hahn   if (isa<VPWidenGEPRecipe, VPDerivedIVRecipe>(VPV))
49bd5e12e6SFlorian Hahn     return all_of(VPV->getDefiningRecipe()->operands(),
50bd5e12e6SFlorian Hahn                   isUniformAfterVectorization);
51bd5e12e6SFlorian Hahn   if (auto *VPI = dyn_cast<VPInstruction>(VPV))
520d39fe6fSFlorian Hahn     return VPI->isSingleScalar() || VPI->isVectorToScalar() ||
530d39fe6fSFlorian Hahn            ((Instruction::isBinaryOp(VPI->getOpcode()) ||
540d39fe6fSFlorian Hahn              VPI->getOpcode() == VPInstruction::PtrAdd) &&
550d39fe6fSFlorian Hahn             all_of(VPI->operands(), isUniformAfterVectorization));
56bd5e12e6SFlorian Hahn   if (auto *IV = dyn_cast<VPDerivedIVRecipe>(VPV))
570d39fe6fSFlorian Hahn     return all_of(IV->operands(), isUniformAfterVectorization);
580d39fe6fSFlorian Hahn 
590eaa69ebSFlorian Hahn   // VPExpandSCEVRecipes must be placed in the entry and are alway uniform.
60bd5e12e6SFlorian Hahn   return isa<VPExpandSCEVRecipe>(VPV);
6171ede8d8SRamkumar Ramachandra }
6271ede8d8SRamkumar Ramachandra 
6371ede8d8SRamkumar Ramachandra /// Return true if \p V is a header mask in \p Plan.
6471ede8d8SRamkumar Ramachandra bool isHeaderMask(const VPValue *V, VPlan &Plan);
658ec40675SFlorian Hahn 
668ec40675SFlorian Hahn /// Checks if \p V is uniform across all VF lanes and UF parts. It is considered
678ec40675SFlorian Hahn /// as such if it is either loop invariant (defined outside the vector region)
688ec40675SFlorian Hahn /// or its operand is known to be uniform across all VFs and UFs (e.g.
698ec40675SFlorian Hahn /// VPDerivedIV or VPCanonicalIVPHI).
708ec40675SFlorian Hahn bool isUniformAcrossVFsAndUFs(VPValue *V);
718ec40675SFlorian Hahn 
72*05fbc383SFlorian Hahn } // namespace vputils
73*05fbc383SFlorian Hahn 
74*05fbc383SFlorian Hahn //===----------------------------------------------------------------------===//
75*05fbc383SFlorian Hahn // Utilities for modifying predecessors and successors of VPlan blocks.
76*05fbc383SFlorian Hahn //===----------------------------------------------------------------------===//
77*05fbc383SFlorian Hahn 
78*05fbc383SFlorian Hahn /// Class that provides utilities for VPBlockBases in VPlan.
79*05fbc383SFlorian Hahn class VPBlockUtils {
80*05fbc383SFlorian Hahn public:
81*05fbc383SFlorian Hahn   VPBlockUtils() = delete;
82*05fbc383SFlorian Hahn 
83*05fbc383SFlorian Hahn   /// Insert disconnected VPBlockBase \p NewBlock after \p BlockPtr. Add \p
84*05fbc383SFlorian Hahn   /// NewBlock as successor of \p BlockPtr and \p BlockPtr as predecessor of \p
85*05fbc383SFlorian Hahn   /// NewBlock, and propagate \p BlockPtr parent to \p NewBlock. \p BlockPtr's
86*05fbc383SFlorian Hahn   /// successors are moved from \p BlockPtr to \p NewBlock. \p NewBlock must
87*05fbc383SFlorian Hahn   /// have neither successors nor predecessors.
88*05fbc383SFlorian Hahn   static void insertBlockAfter(VPBlockBase *NewBlock, VPBlockBase *BlockPtr) {
89*05fbc383SFlorian Hahn     assert(NewBlock->getSuccessors().empty() &&
90*05fbc383SFlorian Hahn            NewBlock->getPredecessors().empty() &&
91*05fbc383SFlorian Hahn            "Can't insert new block with predecessors or successors.");
92*05fbc383SFlorian Hahn     NewBlock->setParent(BlockPtr->getParent());
93*05fbc383SFlorian Hahn     SmallVector<VPBlockBase *> Succs(BlockPtr->successors());
94*05fbc383SFlorian Hahn     for (VPBlockBase *Succ : Succs) {
95*05fbc383SFlorian Hahn       disconnectBlocks(BlockPtr, Succ);
96*05fbc383SFlorian Hahn       connectBlocks(NewBlock, Succ);
97*05fbc383SFlorian Hahn     }
98*05fbc383SFlorian Hahn     connectBlocks(BlockPtr, NewBlock);
99*05fbc383SFlorian Hahn   }
100*05fbc383SFlorian Hahn 
101*05fbc383SFlorian Hahn   /// Insert disconnected block \p NewBlock before \p Blockptr. First
102*05fbc383SFlorian Hahn   /// disconnects all predecessors of \p BlockPtr and connects them to \p
103*05fbc383SFlorian Hahn   /// NewBlock. Add \p NewBlock as predecessor of \p BlockPtr and \p BlockPtr as
104*05fbc383SFlorian Hahn   /// successor of \p NewBlock.
105*05fbc383SFlorian Hahn   static void insertBlockBefore(VPBlockBase *NewBlock, VPBlockBase *BlockPtr) {
106*05fbc383SFlorian Hahn     assert(NewBlock->getSuccessors().empty() &&
107*05fbc383SFlorian Hahn            NewBlock->getPredecessors().empty() &&
108*05fbc383SFlorian Hahn            "Can't insert new block with predecessors or successors.");
109*05fbc383SFlorian Hahn     NewBlock->setParent(BlockPtr->getParent());
110*05fbc383SFlorian Hahn     for (VPBlockBase *Pred : to_vector(BlockPtr->predecessors())) {
111*05fbc383SFlorian Hahn       disconnectBlocks(Pred, BlockPtr);
112*05fbc383SFlorian Hahn       connectBlocks(Pred, NewBlock);
113*05fbc383SFlorian Hahn     }
114*05fbc383SFlorian Hahn     connectBlocks(NewBlock, BlockPtr);
115*05fbc383SFlorian Hahn   }
116*05fbc383SFlorian Hahn 
117*05fbc383SFlorian Hahn   /// Insert disconnected VPBlockBases \p IfTrue and \p IfFalse after \p
118*05fbc383SFlorian Hahn   /// BlockPtr. Add \p IfTrue and \p IfFalse as succesors of \p BlockPtr and \p
119*05fbc383SFlorian Hahn   /// BlockPtr as predecessor of \p IfTrue and \p IfFalse. Propagate \p BlockPtr
120*05fbc383SFlorian Hahn   /// parent to \p IfTrue and \p IfFalse. \p BlockPtr must have no successors
121*05fbc383SFlorian Hahn   /// and \p IfTrue and \p IfFalse must have neither successors nor
122*05fbc383SFlorian Hahn   /// predecessors.
123*05fbc383SFlorian Hahn   static void insertTwoBlocksAfter(VPBlockBase *IfTrue, VPBlockBase *IfFalse,
124*05fbc383SFlorian Hahn                                    VPBlockBase *BlockPtr) {
125*05fbc383SFlorian Hahn     assert(IfTrue->getSuccessors().empty() &&
126*05fbc383SFlorian Hahn            "Can't insert IfTrue with successors.");
127*05fbc383SFlorian Hahn     assert(IfFalse->getSuccessors().empty() &&
128*05fbc383SFlorian Hahn            "Can't insert IfFalse with successors.");
129*05fbc383SFlorian Hahn     BlockPtr->setTwoSuccessors(IfTrue, IfFalse);
130*05fbc383SFlorian Hahn     IfTrue->setPredecessors({BlockPtr});
131*05fbc383SFlorian Hahn     IfFalse->setPredecessors({BlockPtr});
132*05fbc383SFlorian Hahn     IfTrue->setParent(BlockPtr->getParent());
133*05fbc383SFlorian Hahn     IfFalse->setParent(BlockPtr->getParent());
134*05fbc383SFlorian Hahn   }
135*05fbc383SFlorian Hahn 
136*05fbc383SFlorian Hahn   /// Connect VPBlockBases \p From and \p To bi-directionally. If \p PredIdx is
137*05fbc383SFlorian Hahn   /// -1, append \p From to the predecessors of \p To, otherwise set \p To's
138*05fbc383SFlorian Hahn   /// predecessor at \p PredIdx to \p From. If \p SuccIdx is -1, append \p To to
139*05fbc383SFlorian Hahn   /// the successors of \p From, otherwise set \p From's successor at \p SuccIdx
140*05fbc383SFlorian Hahn   /// to \p To. Both VPBlockBases must have the same parent, which can be null.
141*05fbc383SFlorian Hahn   /// Both VPBlockBases can be already connected to other VPBlockBases.
142*05fbc383SFlorian Hahn   static void connectBlocks(VPBlockBase *From, VPBlockBase *To,
143*05fbc383SFlorian Hahn                             unsigned PredIdx = -1u, unsigned SuccIdx = -1u) {
144*05fbc383SFlorian Hahn     assert((From->getParent() == To->getParent()) &&
145*05fbc383SFlorian Hahn            "Can't connect two block with different parents");
146*05fbc383SFlorian Hahn     assert((SuccIdx != -1u || From->getNumSuccessors() < 2) &&
147*05fbc383SFlorian Hahn            "Blocks can't have more than two successors.");
148*05fbc383SFlorian Hahn     if (SuccIdx == -1u)
149*05fbc383SFlorian Hahn       From->appendSuccessor(To);
150*05fbc383SFlorian Hahn     else
151*05fbc383SFlorian Hahn       From->getSuccessors()[SuccIdx] = To;
152*05fbc383SFlorian Hahn 
153*05fbc383SFlorian Hahn     if (PredIdx == -1u)
154*05fbc383SFlorian Hahn       To->appendPredecessor(From);
155*05fbc383SFlorian Hahn     else
156*05fbc383SFlorian Hahn       To->getPredecessors()[PredIdx] = From;
157*05fbc383SFlorian Hahn   }
158*05fbc383SFlorian Hahn 
159*05fbc383SFlorian Hahn   /// Disconnect VPBlockBases \p From and \p To bi-directionally. Remove \p To
160*05fbc383SFlorian Hahn   /// from the successors of \p From and \p From from the predecessors of \p To.
161*05fbc383SFlorian Hahn   static void disconnectBlocks(VPBlockBase *From, VPBlockBase *To) {
162*05fbc383SFlorian Hahn     assert(To && "Successor to disconnect is null.");
163*05fbc383SFlorian Hahn     From->removeSuccessor(To);
164*05fbc383SFlorian Hahn     To->removePredecessor(From);
165*05fbc383SFlorian Hahn   }
166*05fbc383SFlorian Hahn 
167*05fbc383SFlorian Hahn   /// Reassociate all the blocks connected to \p Old so that they now point to
168*05fbc383SFlorian Hahn   /// \p New.
169*05fbc383SFlorian Hahn   static void reassociateBlocks(VPBlockBase *Old, VPBlockBase *New) {
170*05fbc383SFlorian Hahn     for (auto *Pred : to_vector(Old->getPredecessors()))
171*05fbc383SFlorian Hahn       Pred->replaceSuccessor(Old, New);
172*05fbc383SFlorian Hahn     for (auto *Succ : to_vector(Old->getSuccessors()))
173*05fbc383SFlorian Hahn       Succ->replacePredecessor(Old, New);
174*05fbc383SFlorian Hahn     New->setPredecessors(Old->getPredecessors());
175*05fbc383SFlorian Hahn     New->setSuccessors(Old->getSuccessors());
176*05fbc383SFlorian Hahn     Old->clearPredecessors();
177*05fbc383SFlorian Hahn     Old->clearSuccessors();
178*05fbc383SFlorian Hahn   }
179*05fbc383SFlorian Hahn 
180*05fbc383SFlorian Hahn   /// Return an iterator range over \p Range which only includes \p BlockTy
181*05fbc383SFlorian Hahn   /// blocks. The accesses are casted to \p BlockTy.
182*05fbc383SFlorian Hahn   template <typename BlockTy, typename T>
183*05fbc383SFlorian Hahn   static auto blocksOnly(const T &Range) {
184*05fbc383SFlorian Hahn     // Create BaseTy with correct const-ness based on BlockTy.
185*05fbc383SFlorian Hahn     using BaseTy = std::conditional_t<std::is_const<BlockTy>::value,
186*05fbc383SFlorian Hahn                                       const VPBlockBase, VPBlockBase>;
187*05fbc383SFlorian Hahn 
188*05fbc383SFlorian Hahn     // We need to first create an iterator range over (const) BlocktTy & instead
189*05fbc383SFlorian Hahn     // of (const) BlockTy * for filter_range to work properly.
190*05fbc383SFlorian Hahn     auto Mapped =
191*05fbc383SFlorian Hahn         map_range(Range, [](BaseTy *Block) -> BaseTy & { return *Block; });
192*05fbc383SFlorian Hahn     auto Filter = make_filter_range(
193*05fbc383SFlorian Hahn         Mapped, [](BaseTy &Block) { return isa<BlockTy>(&Block); });
194*05fbc383SFlorian Hahn     return map_range(Filter, [](BaseTy &Block) -> BlockTy * {
195*05fbc383SFlorian Hahn       return cast<BlockTy>(&Block);
196*05fbc383SFlorian Hahn     });
197*05fbc383SFlorian Hahn   }
198*05fbc383SFlorian Hahn 
199*05fbc383SFlorian Hahn   /// Inserts \p BlockPtr on the edge between \p From and \p To. That is, update
200*05fbc383SFlorian Hahn   /// \p From's successor to \p To to point to \p BlockPtr and \p To's
201*05fbc383SFlorian Hahn   /// predecessor from \p From to \p BlockPtr. \p From and \p To are added to \p
202*05fbc383SFlorian Hahn   /// BlockPtr's predecessors and successors respectively. There must be a
203*05fbc383SFlorian Hahn   /// single edge between \p From and \p To.
204*05fbc383SFlorian Hahn   static void insertOnEdge(VPBlockBase *From, VPBlockBase *To,
205*05fbc383SFlorian Hahn                            VPBlockBase *BlockPtr) {
206*05fbc383SFlorian Hahn     auto &Successors = From->getSuccessors();
207*05fbc383SFlorian Hahn     auto &Predecessors = To->getPredecessors();
208*05fbc383SFlorian Hahn     assert(count(Successors, To) == 1 && count(Predecessors, From) == 1 &&
209*05fbc383SFlorian Hahn            "must have single between From and To");
210*05fbc383SFlorian Hahn     unsigned SuccIdx = std::distance(Successors.begin(), find(Successors, To));
211*05fbc383SFlorian Hahn     unsigned PredIx =
212*05fbc383SFlorian Hahn         std::distance(Predecessors.begin(), find(Predecessors, From));
213*05fbc383SFlorian Hahn     VPBlockUtils::connectBlocks(From, BlockPtr, -1, SuccIdx);
214*05fbc383SFlorian Hahn     VPBlockUtils::connectBlocks(BlockPtr, To, PredIx, -1);
215*05fbc383SFlorian Hahn   }
216*05fbc383SFlorian Hahn };
217*05fbc383SFlorian Hahn 
218*05fbc383SFlorian Hahn } // namespace llvm
21971ede8d8SRamkumar Ramachandra 
22071ede8d8SRamkumar Ramachandra #endif
221