From f487dfd830255f0b971c2c0596676f2717d6b60b Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Mon, 26 Dec 2022 00:41:12 +0300 Subject: [PATCH] [NFC][Analysis] Implement `getShuffleMaskWithWidestElts()` wrapper (+tests) It will be needed in an upcoming patch to implement some shuffle combining. --- llvm/include/llvm/Analysis/VectorUtils.h | 5 ++++ llvm/lib/Analysis/VectorUtils.cpp | 14 +++++++++ llvm/unittests/Analysis/VectorUtilsTest.cpp | 44 +++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/llvm/include/llvm/Analysis/VectorUtils.h b/llvm/include/llvm/Analysis/VectorUtils.h index cb09a1c..181c5f7 100644 --- a/llvm/include/llvm/Analysis/VectorUtils.h +++ b/llvm/include/llvm/Analysis/VectorUtils.h @@ -407,6 +407,11 @@ void narrowShuffleMaskElts(int Scale, ArrayRef Mask, bool widenShuffleMaskElts(int Scale, ArrayRef Mask, SmallVectorImpl &ScaledMask); +/// Repetitively apply `widenShuffleMaskElts()` for as long as it succeeds, +/// to get the shuffle mask with widest possible elements. +void getShuffleMaskWithWidestElts(ArrayRef Mask, + SmallVectorImpl &ScaledMask); + /// Splits and processes shuffle mask depending on the number of input and /// output registers. The function does 2 main things: 1) splits the /// source/destination vectors into real registers; 2) do the mask analysis to diff --git a/llvm/lib/Analysis/VectorUtils.cpp b/llvm/lib/Analysis/VectorUtils.cpp index bcd748c..1e48d3e2 100644 --- a/llvm/lib/Analysis/VectorUtils.cpp +++ b/llvm/lib/Analysis/VectorUtils.cpp @@ -538,6 +538,20 @@ bool llvm::widenShuffleMaskElts(int Scale, ArrayRef Mask, return true; } +void llvm::getShuffleMaskWithWidestElts(ArrayRef Mask, + SmallVectorImpl &ScaledMask) { + std::array, 2> TmpMasks; + SmallVectorImpl *Output = &TmpMasks[0], *Tmp = &TmpMasks[1]; + ArrayRef InputMask = Mask; + for (unsigned Scale = 2; Scale <= InputMask.size(); ++Scale) { + while (widenShuffleMaskElts(Scale, InputMask, *Output)) { + InputMask = *Output; + std::swap(Output, Tmp); + } + } + ScaledMask.assign(InputMask.begin(), InputMask.end()); +} + void llvm::processShuffleMasks( ArrayRef Mask, unsigned NumOfSrcRegs, unsigned NumOfDestRegs, unsigned NumOfUsedRegs, function_ref NoInputAction, diff --git a/llvm/unittests/Analysis/VectorUtilsTest.cpp b/llvm/unittests/Analysis/VectorUtilsTest.cpp index 143b55b..6d08722 100644 --- a/llvm/unittests/Analysis/VectorUtilsTest.cpp +++ b/llvm/unittests/Analysis/VectorUtilsTest.cpp @@ -166,6 +166,50 @@ TEST_F(BasicTest, widenShuffleMaskElts) { EXPECT_EQ(makeArrayRef(WideMask), makeArrayRef({-2,-3})); } +TEST_F(BasicTest, getShuffleMaskWithWidestElts) { + SmallVector WideMask; + + // can not widen anything here. + getShuffleMaskWithWidestElts({3, 2, 0, -1}, WideMask); + EXPECT_EQ(makeArrayRef(WideMask), makeArrayRef({3, 2, 0, -1})); + + // can't widen non-consecutive 3/2 + getShuffleMaskWithWidestElts({3, 2, 0, -1}, WideMask); + EXPECT_EQ(makeArrayRef(WideMask), makeArrayRef({3, 2, 0, -1})); + + // can always widen identity to single element + getShuffleMaskWithWidestElts({0, 1, 2}, WideMask); + EXPECT_EQ(makeArrayRef(WideMask), makeArrayRef({0})); + + // groups of 4 must be consecutive/undef + getShuffleMaskWithWidestElts( + {12, 13, 14, 15, 8, 9, 10, 11, 0, 1, 2, 3, -1, -1, -1, -1}, WideMask); + EXPECT_EQ(makeArrayRef(WideMask), makeArrayRef({3, 2, 0, -1})); + + // groups of 2 must be consecutive/undef + getShuffleMaskWithWidestElts( + {12, 12, 14, 15, 8, 9, 10, 11, 0, 1, 2, 3, -1, -1, -1, -1}, WideMask); + EXPECT_EQ(makeArrayRef(WideMask), makeArrayRef({12, 12, 14, 15, 8, 9, 10, 11, + 0, 1, 2, 3, -1, -1, -1, -1})); + + // groups of 3 must be consecutive/undef + getShuffleMaskWithWidestElts({6, 7, 8, 0, 1, 2, -1, -1, -1}, WideMask); + EXPECT_EQ(makeArrayRef(WideMask), makeArrayRef({2, 0, -1})); + + // groups of 3 must be consecutive/undef (partial undefs are not ok) + getShuffleMaskWithWidestElts({-1, 7, 8, 0, -1, 2, -1, -1, -1}, WideMask); + EXPECT_EQ(makeArrayRef(WideMask), + makeArrayRef({-1, 7, 8, 0, -1, 2, -1, -1, -1})); + + // negative indexes must match across a wide element + getShuffleMaskWithWidestElts({-1, -2, -1, -1}, WideMask); + EXPECT_EQ(makeArrayRef(WideMask), makeArrayRef({-1, -2, -1, -1})); + + // negative indexes must match across a wide element + getShuffleMaskWithWidestElts({-2, -2, -3, -3}, WideMask); + EXPECT_EQ(makeArrayRef(WideMask), makeArrayRef({-2, -3})); +} + TEST_F(BasicTest, getShuffleDemandedElts) { APInt LHS, RHS; -- 2.7.4