diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h --- a/llvm/lib/Transforms/Vectorize/VPlan.h +++ b/llvm/lib/Transforms/Vectorize/VPlan.h @@ -2201,6 +2201,20 @@ } return Count; } + + /// Return an iterator range over \p Iter which only includes \p BlockTy + /// blocks. The accesses are casted to \p BlockTy. + template static auto blocksOnly(T Iter) { + // We need to first create an iterator range over VPBlockBase & instead of + // VPBlockBase * for filter_range to work properly. + auto Mapped = map_range( + Iter, [](VPBlockBase *Block) -> VPBlockBase & { return *Block; }); + auto Filter = make_filter_range( + Mapped, [](VPBlockBase &Block) { return isa(&Block); }); + return map_range(Filter, [](VPBlockBase &Block) -> BlockTy * { + return cast(&Block); + }); + } }; class VPInterleavedAccessInfo { diff --git a/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp b/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp --- a/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp +++ b/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp @@ -405,6 +405,25 @@ EXPECT_EQ(R2BB2, FromIterator[6]); EXPECT_EQ(R1BB3, FromIterator[7]); + // const VPBasicBlocks only. + FromIterator.clear(); + copy(VPBlockUtils::blocksOnly(depth_first(Start)), + std::back_inserter(FromIterator)); + EXPECT_EQ(6u, FromIterator.size()); + EXPECT_EQ(R1BB1, FromIterator[0]); + EXPECT_EQ(R1BB2, FromIterator[1]); + EXPECT_EQ(R1BB4, FromIterator[2]); + EXPECT_EQ(R2BB1, FromIterator[3]); + EXPECT_EQ(R2BB2, FromIterator[4]); + EXPECT_EQ(R1BB3, FromIterator[5]); + + // VPRegionBlocks only. + SmallVector FromIteratorVPRegion( + VPBlockUtils::blocksOnly(depth_first(Start))); + EXPECT_EQ(2u, FromIteratorVPRegion.size()); + EXPECT_EQ(R1, FromIteratorVPRegion[0]); + EXPECT_EQ(R2, FromIteratorVPRegion[1]); + // Post-order. FromIterator.clear(); copy(post_order(Start), std::back_inserter(FromIterator)); @@ -599,6 +618,14 @@ EXPECT_EQ(R3BB1, FromIterator[5]); EXPECT_EQ(VPBB2, FromIterator[6]); + SmallVector FromIteratorVPBB; + copy(VPBlockUtils::blocksOnly(depth_first(Start)), + std::back_inserter(FromIteratorVPBB)); + EXPECT_EQ(VPBB1, FromIteratorVPBB[0]); + EXPECT_EQ(R2BB1, FromIteratorVPBB[1]); + EXPECT_EQ(R3BB1, FromIteratorVPBB[2]); + EXPECT_EQ(VPBB2, FromIteratorVPBB[3]); + // Post-order. FromIterator.clear(); copy(post_order(Start), std::back_inserter(FromIterator)); @@ -611,6 +638,24 @@ EXPECT_EQ(R1, FromIterator[5]); EXPECT_EQ(VPBB1, FromIterator[6]); + // Post-order, const VPRegionBlocks only. + SmallVector FromIteratorVPRegion( + VPBlockUtils::blocksOnly(post_order(Start))); + EXPECT_EQ(3u, FromIteratorVPRegion.size()); + EXPECT_EQ(R3, FromIteratorVPRegion[0]); + EXPECT_EQ(R2, FromIteratorVPRegion[1]); + EXPECT_EQ(R1, FromIteratorVPRegion[2]); + + // Post-order, VPBasicBlocks only. + FromIterator.clear(); + copy(VPBlockUtils::blocksOnly(post_order(Start)), + std::back_inserter(FromIterator)); + EXPECT_EQ(FromIterator.size(), 4u); + EXPECT_EQ(VPBB2, FromIterator[0]); + EXPECT_EQ(R3BB1, FromIterator[1]); + EXPECT_EQ(R2BB1, FromIterator[2]); + EXPECT_EQ(VPBB1, FromIterator[3]); + // Use Plan to properly clean up created blocks. VPlan Plan; Plan.setEntry(VPBB1);