Index: lib/Transforms/Vectorize/VPlan.h =================================================================== --- lib/Transforms/Vectorize/VPlan.h +++ lib/Transforms/Vectorize/VPlan.h @@ -537,6 +537,10 @@ /// Each recipe prints itself. virtual void print(raw_ostream &O, const Twine &Indent) const = 0; + + /// Unlink this recipe from its current VPBasicBlock and insert it into + /// the VPBasicBlock that MovePos lives in, right after MovePos. + void moveAfter(VPRecipeBase *MovePos); }; /// This is a concrete Recipe that models a single VPlan-level instruction. @@ -908,6 +912,9 @@ inline const VPRecipeBase &back() const { return Recipes.back(); } inline VPRecipeBase &back() { return Recipes.back(); } + /// Returns a reference to the list of recipes. + RecipeListTy &getRecipeList() { return Recipes; } + /// Returns a pointer to a member of the recipe list. static RecipeListTy VPBasicBlock::*getSublistAccess(VPRecipeBase *) { return &VPBasicBlock::Recipes; Index: lib/Transforms/Vectorize/VPlan.cpp =================================================================== --- lib/Transforms/Vectorize/VPlan.cpp +++ lib/Transforms/Vectorize/VPlan.cpp @@ -220,6 +220,12 @@ State->Instance.reset(); } +void VPRecipeBase::moveAfter(VPRecipeBase *InsertPos) { + InsertPos->getParent()->getRecipeList().splice( + std::next(InsertPos->getIterator()), getParent()->getRecipeList(), + getIterator()); +} + void VPInstruction::generateInstruction(VPTransformState &State, unsigned Part) { IRBuilder<> &Builder = State.Builder; Index: unittests/Transforms/CMakeLists.txt =================================================================== --- unittests/Transforms/CMakeLists.txt +++ unittests/Transforms/CMakeLists.txt @@ -1,3 +1,4 @@ add_subdirectory(IPO) add_subdirectory(Scalar) add_subdirectory(Utils) +add_subdirectory(Vectorize) Index: unittests/Transforms/Vectorize/CMakeLists.txt =================================================================== --- /dev/null +++ unittests/Transforms/Vectorize/CMakeLists.txt @@ -0,0 +1,7 @@ +set(LLVM_LINK_COMPONENTS + Vectorize + ) + +add_llvm_unittest(VectorizeTests + VPlanTest.cpp + ) Index: unittests/Transforms/Vectorize/VPlanTest.cpp =================================================================== --- /dev/null +++ unittests/Transforms/Vectorize/VPlanTest.cpp @@ -0,0 +1,52 @@ +//===- llvm/unittest/Analysis/LoopPassManagerTest.cpp - LPM tests ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "../lib/Transforms/Vectorize/VPlan.h" +#include "gtest/gtest.h" + +namespace llvm { +namespace { + +#define CHECK_ITERATOR(Range1, ...) \ + do { \ + std::vector Tmp = {__VA_ARGS__}; \ + EXPECT_EQ((size_t)std::distance(Range1.begin(), Range1.end()), \ + Tmp.size()); \ + for (auto Pair : zip(Range1, make_range(Tmp.begin(), Tmp.end()))) \ + EXPECT_EQ(&std::get<0>(Pair), std::get<1>(Pair)); \ + } while (0) + +TEST(VPInstructionTest, moveAfter) { + VPInstruction *I1 = new VPInstruction(0, {}); + VPInstruction *I2 = new VPInstruction(1, {}); + VPInstruction *I3 = new VPInstruction(2, {}); + + VPBasicBlock VPBB1; + VPBB1.appendRecipe(I1); + VPBB1.appendRecipe(I2); + VPBB1.appendRecipe(I3); + + I1->moveAfter(I2); + + CHECK_ITERATOR(VPBB1, I2, I1, I3); + + VPInstruction *I4 = new VPInstruction(4, {}); + VPInstruction *I5 = new VPInstruction(5, {}); + VPBasicBlock VPBB2; + VPBB2.appendRecipe(I4); + VPBB2.appendRecipe(I5); + + I3->moveAfter(I4); + + CHECK_ITERATOR(VPBB1, I2, I1); + CHECK_ITERATOR(VPBB2, I4, I3, I5); +} + +} // namespace +} // namespace llvm