diff options
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r-- | llvm/lib/Transforms/Vectorize/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/Transforms/Vectorize/VPlan.h | 2 | ||||
-rw-r--r-- | llvm/lib/Transforms/Vectorize/VPlanHCFGTransforms.cpp | 73 | ||||
-rw-r--r-- | llvm/lib/Transforms/Vectorize/VPlanHCFGTransforms.h | 36 |
4 files changed, 112 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/Vectorize/CMakeLists.txt b/llvm/lib/Transforms/Vectorize/CMakeLists.txt index 7c0a39d7ff5..27a4d241b32 100644 --- a/llvm/lib/Transforms/Vectorize/CMakeLists.txt +++ b/llvm/lib/Transforms/Vectorize/CMakeLists.txt @@ -6,6 +6,7 @@ add_llvm_library(LLVMVectorize Vectorize.cpp VPlan.cpp VPlanHCFGBuilder.cpp + VPlanHCFGTransforms.cpp VPlanVerifier.cpp ADDITIONAL_HEADER_DIRS diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h index 0eefa0cea42..86368a8a67f 100644 --- a/llvm/lib/Transforms/Vectorize/VPlan.h +++ b/llvm/lib/Transforms/Vectorize/VPlan.h @@ -568,6 +568,8 @@ public: /// executed, these instructions would always form a single-def expression as /// the VPInstruction is also a single def-use vertex. class VPInstruction : public VPUser, public VPRecipeBase { + friend class VPlanHCFGTransforms; + public: /// VPlan opcodes, extending LLVM IR with idiomatics instructions. enum { Not = Instruction::OtherOpsEnd + 1 }; diff --git a/llvm/lib/Transforms/Vectorize/VPlanHCFGTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanHCFGTransforms.cpp new file mode 100644 index 00000000000..e3cbab077e6 --- /dev/null +++ b/llvm/lib/Transforms/Vectorize/VPlanHCFGTransforms.cpp @@ -0,0 +1,73 @@ +//===-- VPlanHCFGTransforms.cpp - Utility VPlan to VPlan transforms -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file implements a set of utility VPlan to VPlan transformations. +/// +//===----------------------------------------------------------------------===// + +#include "VPlanHCFGTransforms.h" +#include "llvm/ADT/PostOrderIterator.h" + +using namespace llvm; + +void VPlanHCFGTransforms::VPInstructionsToVPRecipes( + VPlanPtr &Plan, + LoopVectorizationLegality::InductionList *Inductions, + SmallPtrSetImpl<Instruction *> &DeadInstructions) { + + VPRegionBlock *TopRegion = dyn_cast<VPRegionBlock>(Plan->getEntry()); + ReversePostOrderTraversal<VPBlockBase *> RPOT(TopRegion->getEntry()); + for (VPBlockBase *Base : RPOT) { + // Do not widen instructions in pre-header and exit blocks. + if (Base->getNumPredecessors() == 0 || Base->getNumSuccessors() == 0) + continue; + + VPBasicBlock *VPBB = Base->getEntryBasicBlock(); + VPRecipeBase *LastRecipe = nullptr; + // Introduce each ingredient into VPlan. + for (auto I = VPBB->begin(), E = VPBB->end(); I != E;) { + VPRecipeBase *Ingredient = &*I++; + // Can only handle VPInstructions. + VPInstruction *VPInst = cast<VPInstruction>(Ingredient); + Instruction *Inst = cast<Instruction>(VPInst->getUnderlyingValue()); + if (DeadInstructions.count(Inst)) { + Ingredient->eraseFromParent(); + continue; + } + + VPRecipeBase *NewRecipe = nullptr; + // Create VPWidenMemoryInstructionRecipe for loads and stores. + if (isa<LoadInst>(Inst) || isa<StoreInst>(Inst)) + NewRecipe = new VPWidenMemoryInstructionRecipe(*Inst, nullptr /*Mask*/); + else if (PHINode *Phi = dyn_cast<PHINode>(Inst)) { + InductionDescriptor II = Inductions->lookup(Phi); + if (II.getKind() == InductionDescriptor::IK_IntInduction || + II.getKind() == InductionDescriptor::IK_FpInduction) { + NewRecipe = new VPWidenIntOrFpInductionRecipe(Phi); + } else + NewRecipe = new VPWidenPHIRecipe(Phi); + } else { + // If the last recipe is a VPWidenRecipe, add Inst to it instead of + // creating a new recipe. + if (VPWidenRecipe *WidenRecipe = + dyn_cast_or_null<VPWidenRecipe>(LastRecipe)) { + WidenRecipe->appendInstruction(Inst); + Ingredient->eraseFromParent(); + continue; + } + NewRecipe = new VPWidenRecipe(Inst); + } + + NewRecipe->insertBefore(Ingredient); + LastRecipe = NewRecipe; + Ingredient->eraseFromParent(); + } + } +} diff --git a/llvm/lib/Transforms/Vectorize/VPlanHCFGTransforms.h b/llvm/lib/Transforms/Vectorize/VPlanHCFGTransforms.h new file mode 100644 index 00000000000..ae549c6871b --- /dev/null +++ b/llvm/lib/Transforms/Vectorize/VPlanHCFGTransforms.h @@ -0,0 +1,36 @@ +//===- VPlanHCFGTransforms.h - Utility VPlan to VPlan transforms ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file provides utility VPlan to VPlan transformations. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_VECTORIZE_VPLANHCFGTRANSFORMS_H +#define LLVM_TRANSFORMS_VECTORIZE_VPLANHCFGTRANSFORMS_H + +#include "VPlan.h" +#include "llvm/IR/Instruction.h" +#include "llvm/Transforms/Vectorize/LoopVectorizationLegality.h" + +namespace llvm { + +class VPlanHCFGTransforms { + +public: + /// Replaces the VPInstructions in \p Plan with corresponding + /// widen recipes. + static void VPInstructionsToVPRecipes( + VPlanPtr &Plan, + LoopVectorizationLegality::InductionList *Inductions, + SmallPtrSetImpl<Instruction *> &DeadInstructions); +}; + +} // namespace llvm + +#endif // LLVM_TRANSFORMS_VECTORIZE_VPLANHCFGTRANSFORMS_H |