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 14 namespace llvm { 15 class ScalarEvolution; 16 class SCEV; 17 } // namespace llvm 18 19 namespace llvm { 20 21 namespace vputils { 22 /// Returns true if only the first lane of \p Def is used. 23 bool onlyFirstLaneUsed(const VPValue *Def); 24 25 /// Returns true if only the first part of \p Def is used. 26 bool 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. 33 VPValue *getOrCreateVPValueForSCEVExpr(VPlan &Plan, const SCEV *Expr, 34 ScalarEvolution &SE); 35 36 /// Return the SCEV expression for \p V. Returns SCEVCouldNotCompute if no 37 /// SCEV expression could be constructed. 38 const SCEV *getSCEVExprForVPValue(VPValue *V, ScalarEvolution &SE); 39 40 /// Returns true if \p VPV is uniform after vectorization. 41 inline bool isUniformAfterVectorization(const VPValue *VPV) { 42 // A value defined outside the vector region must be uniform after 43 // vectorization inside a vector region. 44 if (VPV->isDefinedOutsideLoopRegions()) 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(), 50 isUniformAfterVectorization); 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. 64 bool 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). 70 bool isUniformAcrossVFsAndUFs(VPValue *V); 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. 79 class VPBlockUtils { 80 public: 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. 142 static void connectBlocks(VPBlockBase *From, VPBlockBase *To, 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. 161 static void disconnectBlocks(VPBlockBase *From, VPBlockBase *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; }); 192 auto Filter = make_filter_range( 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. 204 static void insertOnEdge(VPBlockBase *From, VPBlockBase *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 221