1*e60b36cfSFlorian Hahn //===-- VPlanTransforms.cpp - Utility VPlan to VPlan transforms -----------===// 2*e60b36cfSFlorian Hahn // 3*e60b36cfSFlorian Hahn // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*e60b36cfSFlorian Hahn // See https://llvm.org/LICENSE.txt for license information. 5*e60b36cfSFlorian Hahn // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*e60b36cfSFlorian Hahn // 7*e60b36cfSFlorian Hahn //===----------------------------------------------------------------------===// 8*e60b36cfSFlorian Hahn /// 9*e60b36cfSFlorian Hahn /// \file 10*e60b36cfSFlorian Hahn /// This file implements a set of utility VPlan to VPlan transformations. 11*e60b36cfSFlorian Hahn /// 12*e60b36cfSFlorian Hahn //===----------------------------------------------------------------------===// 13*e60b36cfSFlorian Hahn 14*e60b36cfSFlorian Hahn #include "VPlanTransforms.h" 15*e60b36cfSFlorian Hahn #include "llvm/ADT/PostOrderIterator.h" 16*e60b36cfSFlorian Hahn 17*e60b36cfSFlorian Hahn using namespace llvm; 18*e60b36cfSFlorian Hahn 19*e60b36cfSFlorian Hahn void VPlanTransforms::VPInstructionsToVPRecipes( 20*e60b36cfSFlorian Hahn Loop *OrigLoop, VPlanPtr &Plan, 21*e60b36cfSFlorian Hahn LoopVectorizationLegality::InductionList *Inductions, 22*e60b36cfSFlorian Hahn SmallPtrSetImpl<Instruction *> &DeadInstructions) { 23*e60b36cfSFlorian Hahn 24*e60b36cfSFlorian Hahn auto *TopRegion = cast<VPRegionBlock>(Plan->getEntry()); 25*e60b36cfSFlorian Hahn ReversePostOrderTraversal<VPBlockBase *> RPOT(TopRegion->getEntry()); 26*e60b36cfSFlorian Hahn 27*e60b36cfSFlorian Hahn // Condition bit VPValues get deleted during transformation to VPRecipes. 28*e60b36cfSFlorian Hahn // Create new VPValues and save away as condition bits. These will be deleted 29*e60b36cfSFlorian Hahn // after finalizing the vector IR basic blocks. 30*e60b36cfSFlorian Hahn for (VPBlockBase *Base : RPOT) { 31*e60b36cfSFlorian Hahn VPBasicBlock *VPBB = Base->getEntryBasicBlock(); 32*e60b36cfSFlorian Hahn if (auto *CondBit = VPBB->getCondBit()) { 33*e60b36cfSFlorian Hahn auto *NCondBit = new VPValue(CondBit->getUnderlyingValue()); 34*e60b36cfSFlorian Hahn VPBB->setCondBit(NCondBit); 35*e60b36cfSFlorian Hahn Plan->addCBV(NCondBit); 36*e60b36cfSFlorian Hahn } 37*e60b36cfSFlorian Hahn } 38*e60b36cfSFlorian Hahn for (VPBlockBase *Base : RPOT) { 39*e60b36cfSFlorian Hahn // Do not widen instructions in pre-header and exit blocks. 40*e60b36cfSFlorian Hahn if (Base->getNumPredecessors() == 0 || Base->getNumSuccessors() == 0) 41*e60b36cfSFlorian Hahn continue; 42*e60b36cfSFlorian Hahn 43*e60b36cfSFlorian Hahn VPBasicBlock *VPBB = Base->getEntryBasicBlock(); 44*e60b36cfSFlorian Hahn VPRecipeBase *LastRecipe = nullptr; 45*e60b36cfSFlorian Hahn // Introduce each ingredient into VPlan. 46*e60b36cfSFlorian Hahn for (auto I = VPBB->begin(), E = VPBB->end(); I != E;) { 47*e60b36cfSFlorian Hahn VPRecipeBase *Ingredient = &*I++; 48*e60b36cfSFlorian Hahn // Can only handle VPInstructions. 49*e60b36cfSFlorian Hahn VPInstruction *VPInst = cast<VPInstruction>(Ingredient); 50*e60b36cfSFlorian Hahn Instruction *Inst = cast<Instruction>(VPInst->getUnderlyingValue()); 51*e60b36cfSFlorian Hahn if (DeadInstructions.count(Inst)) { 52*e60b36cfSFlorian Hahn Ingredient->eraseFromParent(); 53*e60b36cfSFlorian Hahn continue; 54*e60b36cfSFlorian Hahn } 55*e60b36cfSFlorian Hahn 56*e60b36cfSFlorian Hahn VPRecipeBase *NewRecipe = nullptr; 57*e60b36cfSFlorian Hahn // Create VPWidenMemoryInstructionRecipe for loads and stores. 58*e60b36cfSFlorian Hahn if (isa<LoadInst>(Inst) || isa<StoreInst>(Inst)) 59*e60b36cfSFlorian Hahn NewRecipe = new VPWidenMemoryInstructionRecipe(*Inst, nullptr /*Mask*/); 60*e60b36cfSFlorian Hahn else if (PHINode *Phi = dyn_cast<PHINode>(Inst)) { 61*e60b36cfSFlorian Hahn InductionDescriptor II = Inductions->lookup(Phi); 62*e60b36cfSFlorian Hahn if (II.getKind() == InductionDescriptor::IK_IntInduction || 63*e60b36cfSFlorian Hahn II.getKind() == InductionDescriptor::IK_FpInduction) { 64*e60b36cfSFlorian Hahn NewRecipe = new VPWidenIntOrFpInductionRecipe(Phi); 65*e60b36cfSFlorian Hahn } else 66*e60b36cfSFlorian Hahn NewRecipe = new VPWidenPHIRecipe(Phi); 67*e60b36cfSFlorian Hahn } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Inst)) { 68*e60b36cfSFlorian Hahn NewRecipe = new VPWidenGEPRecipe(GEP, OrigLoop); 69*e60b36cfSFlorian Hahn } else { 70*e60b36cfSFlorian Hahn // If the last recipe is a VPWidenRecipe, add Inst to it instead of 71*e60b36cfSFlorian Hahn // creating a new recipe. 72*e60b36cfSFlorian Hahn if (VPWidenRecipe *WidenRecipe = 73*e60b36cfSFlorian Hahn dyn_cast_or_null<VPWidenRecipe>(LastRecipe)) { 74*e60b36cfSFlorian Hahn WidenRecipe->appendInstruction(Inst); 75*e60b36cfSFlorian Hahn Ingredient->eraseFromParent(); 76*e60b36cfSFlorian Hahn continue; 77*e60b36cfSFlorian Hahn } 78*e60b36cfSFlorian Hahn NewRecipe = new VPWidenRecipe(Inst); 79*e60b36cfSFlorian Hahn } 80*e60b36cfSFlorian Hahn 81*e60b36cfSFlorian Hahn NewRecipe->insertBefore(Ingredient); 82*e60b36cfSFlorian Hahn LastRecipe = NewRecipe; 83*e60b36cfSFlorian Hahn Ingredient->eraseFromParent(); 84*e60b36cfSFlorian Hahn } 85*e60b36cfSFlorian Hahn } 86*e60b36cfSFlorian Hahn } 87