1e60b36cfSFlorian Hahn //===-- VPlanTransforms.cpp - Utility VPlan to VPlan transforms -----------===// 2e60b36cfSFlorian Hahn // 3e60b36cfSFlorian Hahn // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e60b36cfSFlorian Hahn // See https://llvm.org/LICENSE.txt for license information. 5e60b36cfSFlorian Hahn // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e60b36cfSFlorian Hahn // 7e60b36cfSFlorian Hahn //===----------------------------------------------------------------------===// 8e60b36cfSFlorian Hahn /// 9e60b36cfSFlorian Hahn /// \file 10e60b36cfSFlorian Hahn /// This file implements a set of utility VPlan to VPlan transformations. 11e60b36cfSFlorian Hahn /// 12e60b36cfSFlorian Hahn //===----------------------------------------------------------------------===// 13e60b36cfSFlorian Hahn 14e60b36cfSFlorian Hahn #include "VPlanTransforms.h" 15e60b36cfSFlorian Hahn #include "llvm/ADT/PostOrderIterator.h" 16e60b36cfSFlorian Hahn 17e60b36cfSFlorian Hahn using namespace llvm; 18e60b36cfSFlorian Hahn 19e60b36cfSFlorian Hahn void VPlanTransforms::VPInstructionsToVPRecipes( 20e60b36cfSFlorian Hahn Loop *OrigLoop, VPlanPtr &Plan, 21d0d38df0SDavid Green LoopVectorizationLegality::InductionList &Inductions, 22e60b36cfSFlorian Hahn SmallPtrSetImpl<Instruction *> &DeadInstructions) { 23e60b36cfSFlorian Hahn 24e60b36cfSFlorian Hahn auto *TopRegion = cast<VPRegionBlock>(Plan->getEntry()); 25e60b36cfSFlorian Hahn ReversePostOrderTraversal<VPBlockBase *> RPOT(TopRegion->getEntry()); 26e60b36cfSFlorian Hahn 27e60b36cfSFlorian Hahn // Condition bit VPValues get deleted during transformation to VPRecipes. 28e60b36cfSFlorian Hahn // Create new VPValues and save away as condition bits. These will be deleted 29e60b36cfSFlorian Hahn // after finalizing the vector IR basic blocks. 30e60b36cfSFlorian Hahn for (VPBlockBase *Base : RPOT) { 31e60b36cfSFlorian Hahn VPBasicBlock *VPBB = Base->getEntryBasicBlock(); 32e60b36cfSFlorian Hahn if (auto *CondBit = VPBB->getCondBit()) { 33e60b36cfSFlorian Hahn auto *NCondBit = new VPValue(CondBit->getUnderlyingValue()); 34e60b36cfSFlorian Hahn VPBB->setCondBit(NCondBit); 35e60b36cfSFlorian Hahn Plan->addCBV(NCondBit); 36e60b36cfSFlorian Hahn } 37e60b36cfSFlorian Hahn } 38e60b36cfSFlorian Hahn for (VPBlockBase *Base : RPOT) { 39e60b36cfSFlorian Hahn // Do not widen instructions in pre-header and exit blocks. 40e60b36cfSFlorian Hahn if (Base->getNumPredecessors() == 0 || Base->getNumSuccessors() == 0) 41e60b36cfSFlorian Hahn continue; 42e60b36cfSFlorian Hahn 43e60b36cfSFlorian Hahn VPBasicBlock *VPBB = Base->getEntryBasicBlock(); 44e60b36cfSFlorian Hahn // Introduce each ingredient into VPlan. 45e60b36cfSFlorian Hahn for (auto I = VPBB->begin(), E = VPBB->end(); I != E;) { 46e60b36cfSFlorian Hahn VPRecipeBase *Ingredient = &*I++; 47e60b36cfSFlorian Hahn // Can only handle VPInstructions. 48e60b36cfSFlorian Hahn VPInstruction *VPInst = cast<VPInstruction>(Ingredient); 49e60b36cfSFlorian Hahn Instruction *Inst = cast<Instruction>(VPInst->getUnderlyingValue()); 50e60b36cfSFlorian Hahn if (DeadInstructions.count(Inst)) { 5176afbf60SFlorian Hahn VPValue DummyValue; 52348d85a6SFlorian Hahn VPInst->replaceAllUsesWith(&DummyValue); 53e60b36cfSFlorian Hahn Ingredient->eraseFromParent(); 54e60b36cfSFlorian Hahn continue; 55e60b36cfSFlorian Hahn } 56e60b36cfSFlorian Hahn 57e60b36cfSFlorian Hahn VPRecipeBase *NewRecipe = nullptr; 58e60b36cfSFlorian Hahn // Create VPWidenMemoryInstructionRecipe for loads and stores. 59078c8633SGil Rapaport if (LoadInst *Load = dyn_cast<LoadInst>(Inst)) 608647a72cSGil Rapaport NewRecipe = new VPWidenMemoryInstructionRecipe( 61078c8633SGil Rapaport *Load, Plan->getOrAddVPValue(getLoadStorePointerOperand(Inst)), 628647a72cSGil Rapaport nullptr /*Mask*/); 63078c8633SGil Rapaport else if (StoreInst *Store = dyn_cast<StoreInst>(Inst)) 64078c8633SGil Rapaport NewRecipe = new VPWidenMemoryInstructionRecipe( 65078c8633SGil Rapaport *Store, Plan->getOrAddVPValue(getLoadStorePointerOperand(Inst)), 66078c8633SGil Rapaport Plan->getOrAddVPValue(Store->getValueOperand()), nullptr /*Mask*/); 67e60b36cfSFlorian Hahn else if (PHINode *Phi = dyn_cast<PHINode>(Inst)) { 68d0d38df0SDavid Green InductionDescriptor II = Inductions.lookup(Phi); 69e60b36cfSFlorian Hahn if (II.getKind() == InductionDescriptor::IK_IntInduction || 70e60b36cfSFlorian Hahn II.getKind() == InductionDescriptor::IK_FpInduction) { 71816dba48SFlorian Hahn VPValue *Start = Plan->getOrAddVPValue(II.getStartValue()); 72*daaa0e35SFlorian Hahn NewRecipe = new VPWidenIntOrFpInductionRecipe(Phi, Start, nullptr); 73e60b36cfSFlorian Hahn } else 74e60b36cfSFlorian Hahn NewRecipe = new VPWidenPHIRecipe(Phi); 75e60b36cfSFlorian Hahn } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Inst)) { 76c0cdba72SFlorian Hahn NewRecipe = new VPWidenGEPRecipe( 77c0cdba72SFlorian Hahn GEP, Plan->mapToVPValues(GEP->operands()), OrigLoop); 7849d00824SFlorian Hahn } else 79e8937985SFlorian Hahn NewRecipe = 80e8937985SFlorian Hahn new VPWidenRecipe(*Inst, Plan->mapToVPValues(Inst->operands())); 81e60b36cfSFlorian Hahn 82e60b36cfSFlorian Hahn NewRecipe->insertBefore(Ingredient); 8376afbf60SFlorian Hahn if (NewRecipe->getNumDefinedValues() == 1) 8476afbf60SFlorian Hahn VPInst->replaceAllUsesWith(NewRecipe->getVPValue()); 8576afbf60SFlorian Hahn else 8676afbf60SFlorian Hahn assert(NewRecipe->getNumDefinedValues() == 0 && 8776afbf60SFlorian Hahn "Only recpies with zero or one defined values expected"); 88e60b36cfSFlorian Hahn Ingredient->eraseFromParent(); 89e60b36cfSFlorian Hahn } 90e60b36cfSFlorian Hahn } 91e60b36cfSFlorian Hahn } 92