[llvm] [SLP] Create groups before sorting Phis (PR #111174)

Alexey Bataev via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 4 09:27:18 PDT 2024


================
@@ -5448,40 +5448,136 @@ BoUpSLP::getReorderingData(const TreeEntry &TE, bool TopToBottom) {
     if (!TE.ReorderIndices.empty())
       return TE.ReorderIndices;
 
-    auto PHICompare = [&](unsigned I1, unsigned I2) {
-      Value *V1 = TE.Scalars[I1];
-      Value *V2 = TE.Scalars[I2];
-      if (V1 == V2 || (V1->getNumUses() == 0 && V2->getNumUses() == 0))
-        return false;
-      if (V1->getNumUses() < V2->getNumUses())
-        return true;
-      if (V1->getNumUses() > V2->getNumUses())
-        return false;
-      auto *FirstUserOfPhi1 = cast<Instruction>(*V1->user_begin());
-      auto *FirstUserOfPhi2 = cast<Instruction>(*V2->user_begin());
-      if (auto *IE1 = dyn_cast<InsertElementInst>(FirstUserOfPhi1))
-        if (auto *IE2 = dyn_cast<InsertElementInst>(FirstUserOfPhi2)) {
-          if (!areTwoInsertFromSameBuildVector(
-                  IE1, IE2,
-                  [](InsertElementInst *II) { return II->getOperand(0); }))
-            return I1 < I2;
-          return getElementIndex(IE1) < getElementIndex(IE2);
-        }
-      if (auto *EE1 = dyn_cast<ExtractElementInst>(FirstUserOfPhi1))
-        if (auto *EE2 = dyn_cast<ExtractElementInst>(FirstUserOfPhi2)) {
-          if (EE1->getOperand(0) != EE2->getOperand(0))
-            return I1 < I2;
-          return getElementIndex(EE1) < getElementIndex(EE2);
-        }
-      return I1 < I2;
-    };
-    SmallDenseMap<unsigned, unsigned, 16> PhiToId;
+    DenseMap<unsigned, unsigned> PhiToId;
     SmallVector<unsigned> Phis(TE.Scalars.size());
     std::iota(Phis.begin(), Phis.end(), 0);
+
+    BitVector Seen(Phis.size());
+    SmallVector<SmallVector<unsigned>> Groups;
+    Groups.resize(Phis.size(), {});
+
+    for (auto const Phidx : Phis) {
+      // We've already found a group for this Phidx
+      if (Seen.test(Phidx))
+        continue;
+
+      Groups[Phidx].push_back(Phidx);
+
+      auto UserIterPhi1 = TE.Scalars[Phidx]->user_begin();
+      if (UserIterPhi1.atEnd())
+        continue;
+
+      auto *FirstUserOfPhi1 = cast<Instruction>(*UserIterPhi1);
+
+      unsigned Count = 0;
+      if (auto *IE1 = dyn_cast<InsertElementInst>(FirstUserOfPhi1)) {
+        auto Width = IE1->getType()->getElementCount();
+        assert(!Width.isScalable());
+        Count = Width.getFixedValue() - 1;
+      } else if (auto *EE1 = dyn_cast<ExtractElementInst>(FirstUserOfPhi1)) {
+        // Count is unused in the case of extract element instructions.
+        Count = -1;
+      }
+
+      for (auto const PhidxB : ArrayRef(Phis).drop_front(Phidx + 1)) {
+
----------------
alexey-bataev wrote:

Again, O(N^2). I don't like it, it increases compile time. Alternative approach is here

https://github.com/llvm/llvm-project/pull/110529

https://github.com/llvm/llvm-project/pull/111174


More information about the llvm-commits mailing list