[Hexagon] Better detection of impossible completions to perfect shuffles
authorKrzysztof Parzyszek <kparzysz@quicinc.com>
Mon, 5 Dec 2022 20:21:21 +0000 (12:21 -0800)
committerKrzysztof Parzyszek <kparzysz@quicinc.com>
Mon, 5 Dec 2022 20:40:08 +0000 (12:40 -0800)
If there is an entry P that has C bits set, it could become one of C
different possibilities. If P occurs more than C times, then there are
no valid completions.

llvm/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp
llvm/test/CodeGen/Hexagon/autohvx/isel-shuffle-no-perfect-completion.ll [new file with mode: 0644]

index b529fae..eb67b67 100644 (file)
@@ -1957,6 +1957,27 @@ SmallVector<uint32_t, 8> HvxSelector::getPerfectCompletions(ShuffleMask SM,
   // are exactly the same as in s1, which means that they are exactly the
   // same as in P. This implies that P == Q.
 
+  // There can be a situation where there are more entries with the same
+  // bits set than there are set bits (e.g. value 9 occuring more than 2
+  // times). In such cases it will be impossible to complete this to a
+  // perfect shuffle.
+  SmallVector<uint32_t, 8> Sorted(Worklist);
+  llvm::sort(Sorted.begin(), Sorted.end());
+
+  for (unsigned I = 0, E = Sorted.size(); I != E;) {
+    unsigned P = Sorted[I], Count = 1;
+    while (++I != E && P == Sorted[I])
+      ++Count;
+    if (countPopulation(P) < Count) {
+      // Reset all occurences of P, if there are more occurrences of P
+      // than there are bits in P.
+      for_each(Worklist, [P](unsigned &Q) {
+        if (Q == P)
+          Q = 0;
+      });
+    }
+  }
+
   return Worklist;
 }
 
@@ -1981,6 +2002,17 @@ HvxSelector::completeToPerfect(ArrayRef<uint32_t> Completions, unsigned Width) {
     Comps[I] = T;
   }
 
+#ifndef NDEBUG
+  // Check that we have generated a valid completion.
+  uint32_t OrAll = 0;
+  for (unsigned I = 0, E = Comps.size(); I != E; ++I) {
+    uint32_t C = Comps[I];
+    assert(isPowerOf2_32(C));
+    OrAll |= C;
+  }
+  assert(OrAll == (1u << Width) -1);
+#endif
+
   return Comps;
 }
 
@@ -2280,7 +2312,9 @@ OpRef HvxSelector::perfect(ShuffleMask SM, OpRef Va, ResultStack &Results) {
   if (llvm::any_of(Comps, [](uint32_t P) { return P == 0; }))
     return OpRef::fail();
 
+dbgs() << "Comps:["; for (unsigned I : Comps) dbgs() << ' ' << I; dbgs() << " ]\n";
   auto Pick = completeToPerfect(Comps, LogLen);
+dbgs() << "Pick:["; for (unsigned I : Pick) dbgs() << ' ' << I; dbgs() << " ]\n";
   for (unsigned I = 0; I != LogLen; ++I)
     Perm[I] = Log2_32(Pick[I]);
 
diff --git a/llvm/test/CodeGen/Hexagon/autohvx/isel-shuffle-no-perfect-completion.ll b/llvm/test/CodeGen/Hexagon/autohvx/isel-shuffle-no-perfect-completion.ll
new file mode 100644 (file)
index 0000000..b606608
--- /dev/null
@@ -0,0 +1,11 @@
+; RUN: llc -march=hexagon < %s | FileCheck %s
+
+; Check that this doesn't end up being an entirely perfect shuffle.
+; CHECK: vshuff
+; CHECK-NOT: vdeal
+define <32 x i32> @f0(<32 x i32> %a0, <32 x i32> %a1) #0 {
+  %v0 = shufflevector <32 x i32> %a0, <32 x i32> %a1, <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+  ret <32 x i32> %v0
+}
+
+attributes #0 = { nounwind memory(none) "target-features"="+hvxv62,+hvx-length128b" }