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 Andric void 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