[NFC][Analysis] Implement `getShuffleMaskWithWidestElts()` wrapper (+tests)
authorRoman Lebedev <lebedev.ri@gmail.com>
Sun, 25 Dec 2022 21:41:12 +0000 (00:41 +0300)
committerRoman Lebedev <lebedev.ri@gmail.com>
Sun, 25 Dec 2022 22:04:48 +0000 (01:04 +0300)
It will be needed in an upcoming patch to implement some shuffle combining.

llvm/include/llvm/Analysis/VectorUtils.h
llvm/lib/Analysis/VectorUtils.cpp
llvm/unittests/Analysis/VectorUtilsTest.cpp

index cb09a1c..181c5f7 100644 (file)
@@ -407,6 +407,11 @@ void narrowShuffleMaskElts(int Scale, ArrayRef<int> Mask,
 bool widenShuffleMaskElts(int Scale, ArrayRef<int> Mask,
                           SmallVectorImpl<int> &ScaledMask);
 
+/// Repetitively apply `widenShuffleMaskElts()` for as long as it succeeds,
+/// to get the shuffle mask with widest possible elements.
+void getShuffleMaskWithWidestElts(ArrayRef<int> Mask,
+                                  SmallVectorImpl<int> &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
index bcd748c..1e48d3e 100644 (file)
@@ -538,6 +538,20 @@ bool llvm::widenShuffleMaskElts(int Scale, ArrayRef<int> Mask,
   return true;
 }
 
+void llvm::getShuffleMaskWithWidestElts(ArrayRef<int> Mask,
+                                        SmallVectorImpl<int> &ScaledMask) {
+  std::array<SmallVector<int, 16>, 2> TmpMasks;
+  SmallVectorImpl<int> *Output = &TmpMasks[0], *Tmp = &TmpMasks[1];
+  ArrayRef<int> 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<int> Mask, unsigned NumOfSrcRegs, unsigned NumOfDestRegs,
     unsigned NumOfUsedRegs, function_ref<void()> NoInputAction,
index 143b55b..6d08722 100644 (file)
@@ -166,6 +166,50 @@ TEST_F(BasicTest, widenShuffleMaskElts) {
   EXPECT_EQ(makeArrayRef(WideMask), makeArrayRef({-2,-3}));
 }
 
+TEST_F(BasicTest, getShuffleMaskWithWidestElts) {
+  SmallVector<int, 16> 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;