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