14ba319b5SDimitry Andric //===-- VPlanHCFGTransforms.cpp - Utility VPlan to VPlan transforms -------===// 24ba319b5SDimitry Andric // 34ba319b5SDimitry Andric // The LLVM Compiler Infrastructure 44ba319b5SDimitry Andric // 54ba319b5SDimitry Andric // This file is distributed under the University of Illinois Open Source 64ba319b5SDimitry Andric // License. See LICENSE.TXT for details. 74ba319b5SDimitry Andric // 84ba319b5SDimitry Andric //===----------------------------------------------------------------------===// 94ba319b5SDimitry Andric /// 104ba319b5SDimitry Andric /// \file 114ba319b5SDimitry Andric /// This file implements a set of utility VPlan to VPlan transformations. 124ba319b5SDimitry Andric /// 134ba319b5SDimitry Andric //===----------------------------------------------------------------------===// 144ba319b5SDimitry Andric 154ba319b5SDimitry Andric #include "VPlanHCFGTransforms.h" 164ba319b5SDimitry Andric #include "llvm/ADT/PostOrderIterator.h" 174ba319b5SDimitry Andric 184ba319b5SDimitry Andric using namespace llvm; 194ba319b5SDimitry Andric VPInstructionsToVPRecipes(VPlanPtr & Plan,LoopVectorizationLegality::InductionList * Inductions,SmallPtrSetImpl<Instruction * > & DeadInstructions)204ba319b5SDimitry Andricvoid VPlanHCFGTransforms::VPInstructionsToVPRecipes( 214ba319b5SDimitry Andric VPlanPtr &Plan, 224ba319b5SDimitry Andric LoopVectorizationLegality::InductionList *Inductions, 234ba319b5SDimitry Andric SmallPtrSetImpl<Instruction *> &DeadInstructions) { 244ba319b5SDimitry Andric 254ba319b5SDimitry Andric VPRegionBlock *TopRegion = dyn_cast<VPRegionBlock>(Plan->getEntry()); 264ba319b5SDimitry Andric ReversePostOrderTraversal<VPBlockBase *> RPOT(TopRegion->getEntry()); 27*b5893f02SDimitry Andric 28*b5893f02SDimitry Andric // Condition bit VPValues get deleted during transformation to VPRecipes. 29*b5893f02SDimitry Andric // Create new VPValues and save away as condition bits. These will be deleted 30*b5893f02SDimitry Andric // after finalizing the vector IR basic blocks. 31*b5893f02SDimitry Andric for (VPBlockBase *Base : RPOT) { 32*b5893f02SDimitry Andric VPBasicBlock *VPBB = Base->getEntryBasicBlock(); 33*b5893f02SDimitry Andric if (auto *CondBit = VPBB->getCondBit()) { 34*b5893f02SDimitry Andric auto *NCondBit = new VPValue(CondBit->getUnderlyingValue()); 35*b5893f02SDimitry Andric VPBB->setCondBit(NCondBit); 36*b5893f02SDimitry Andric Plan->addCBV(NCondBit); 37*b5893f02SDimitry Andric } 38*b5893f02SDimitry Andric } 394ba319b5SDimitry Andric for (VPBlockBase *Base : RPOT) { 404ba319b5SDimitry Andric // Do not widen instructions in pre-header and exit blocks. 414ba319b5SDimitry Andric if (Base->getNumPredecessors() == 0 || Base->getNumSuccessors() == 0) 424ba319b5SDimitry Andric continue; 434ba319b5SDimitry Andric 444ba319b5SDimitry Andric VPBasicBlock *VPBB = Base->getEntryBasicBlock(); 454ba319b5SDimitry Andric VPRecipeBase *LastRecipe = nullptr; 464ba319b5SDimitry Andric // Introduce each ingredient into VPlan. 474ba319b5SDimitry Andric for (auto I = VPBB->begin(), E = VPBB->end(); I != E;) { 484ba319b5SDimitry Andric VPRecipeBase *Ingredient = &*I++; 494ba319b5SDimitry Andric // Can only handle VPInstructions. 504ba319b5SDimitry Andric VPInstruction *VPInst = cast<VPInstruction>(Ingredient); 514ba319b5SDimitry Andric Instruction *Inst = cast<Instruction>(VPInst->getUnderlyingValue()); 524ba319b5SDimitry Andric if (DeadInstructions.count(Inst)) { 534ba319b5SDimitry Andric Ingredient->eraseFromParent(); 544ba319b5SDimitry Andric continue; 554ba319b5SDimitry Andric } 564ba319b5SDimitry Andric 574ba319b5SDimitry Andric VPRecipeBase *NewRecipe = nullptr; 584ba319b5SDimitry Andric // Create VPWidenMemoryInstructionRecipe for loads and stores. 594ba319b5SDimitry Andric if (isa<LoadInst>(Inst) || isa<StoreInst>(Inst)) 604ba319b5SDimitry Andric NewRecipe = new VPWidenMemoryInstructionRecipe(*Inst, nullptr /*Mask*/); 614ba319b5SDimitry Andric else if (PHINode *Phi = dyn_cast<PHINode>(Inst)) { 624ba319b5SDimitry Andric InductionDescriptor II = Inductions->lookup(Phi); 634ba319b5SDimitry Andric if (II.getKind() == InductionDescriptor::IK_IntInduction || 644ba319b5SDimitry Andric II.getKind() == InductionDescriptor::IK_FpInduction) { 654ba319b5SDimitry Andric NewRecipe = new VPWidenIntOrFpInductionRecipe(Phi); 664ba319b5SDimitry Andric } else 674ba319b5SDimitry Andric NewRecipe = new VPWidenPHIRecipe(Phi); 684ba319b5SDimitry Andric } else { 694ba319b5SDimitry Andric // If the last recipe is a VPWidenRecipe, add Inst to it instead of 704ba319b5SDimitry Andric // creating a new recipe. 714ba319b5SDimitry Andric if (VPWidenRecipe *WidenRecipe = 724ba319b5SDimitry Andric dyn_cast_or_null<VPWidenRecipe>(LastRecipe)) { 734ba319b5SDimitry Andric WidenRecipe->appendInstruction(Inst); 744ba319b5SDimitry Andric Ingredient->eraseFromParent(); 754ba319b5SDimitry Andric continue; 764ba319b5SDimitry Andric } 774ba319b5SDimitry Andric NewRecipe = new VPWidenRecipe(Inst); 784ba319b5SDimitry Andric } 794ba319b5SDimitry Andric 804ba319b5SDimitry Andric NewRecipe->insertBefore(Ingredient); 814ba319b5SDimitry Andric LastRecipe = NewRecipe; 824ba319b5SDimitry Andric Ingredient->eraseFromParent(); 834ba319b5SDimitry Andric } 844ba319b5SDimitry Andric } 854ba319b5SDimitry Andric } 86