Bug type: crash
Component: SLPVectorizer
Bug location: llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp: BoUpSLP::buildTree_rec
Issue title: SLP Vectorizer crash due to commit ca654acc16c43191228eadfec8f7241dca10b0c3
Labels: llvm:SLPVectorizer
crash
Reported by: ivankelarev

ca654acc16c43191228eadfec8f7241dca10b0c3 change in SLP Vectorizer causes a crash for this test case:

```
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

define void @a_(double %c__fetch.3) {
alloca_0:
  %mul.3 = fmul double 0.000000e+00, %c__fetch.3
  %mul.4 = fmul double 0.000000e+00, 0.000000e+00
  br label %loop.69

loop.69:                                          ; preds = %loop.69, %alloca_0
  %t48.0 = phi double [ 0.000000e+00, %alloca_0 ], [ %5, %loop.69 ]
  %t50.0 = phi double [ 0.000000e+00, %alloca_0 ], [ %3, %loop.69 ]
  %t52.0 = phi double [ 0.000000e+00, %alloca_0 ], [ %7, %loop.69 ]
  %0 = fmul double %t52.0, %mul.3
  %1 = fmul double %t48.0, %mul.4
  %2 = fadd double %1, %0
  %3 = fadd double %2, 0.000000e+00
  %4 = fmul double 0.000000e+00, %mul.3
  %5 = fadd double 0.000000e+00, %4
  %6 = fmul double 0.000000e+00, %mul.4
  %7 = fadd double 0.000000e+00, %6
  br label %loop.69
}
```

After slp-vectorizer pass IR is being transformed to as incorrect one:
```
define void @a_(double %c__fetch.3) {
alloca_0:
  %0 = shufflevector <2 x double> %2, <2 x double> <double 0.000000e+00, double poison>, <2 x i32> <i32 2, i32 0>
  %1 = fmul <2 x double> zeroinitializer, %0
  %2 = insertelement <2 x double> <double poison, double 0.000000e+00>, double %c__fetch.3, i32 0
  %3 = fmul <2 x double> zeroinitializer, %2
  br label %loop.69

loop.69:                                          ; preds = %loop.69, %alloca_0
  %t50.0 = phi double [ 0.000000e+00, %alloca_0 ], [ %9, %loop.69 ]
  %4 = phi <2 x double> [ zeroinitializer, %alloca_0 ], [ %11, %loop.69 ]
  %5 = fmul <2 x double> %4, %1
  %6 = extractelement <2 x double> %5, i32 0
  %7 = extractelement <2 x double> %5, i32 1
  %8 = fadd double %6, %7
  %9 = fadd double %8, 0.000000e+00
  %10 = fmul <2 x double> zeroinitializer, %3
  %11 = fadd <2 x double> zeroinitializer, %10
  br label %loop.69
}
```

Error message:

```
Instruction does not dominate all uses!
  %2 = insertelement <2 x double> <double poison, double 0.000000e+00>, double %c__fetch.3, i32 0
  %0 = shufflevector <2 x double> %2, <2 x double> <double 0.000000e+00, double poison>, <2 x i32> <i32 2, i32 0>
LLVM ERROR: Broken module found, compilation aborted!
```

Reverting the mentioned commit makes this test pass. @alexey-bataev could you please take a look?


Comments: author: ivankelarev
body: Update: It appears that the mentioned commit merely obscures a more fundamental issue. The following test continues to fail even after the commit has been reverted:

```
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

define void @a_(double %c__fetch.3) {
alloca_0:
  %mul.3 = fmul double 0.000000e+00, %c__fetch.3
  %mul.4 = fmul double 0.000000e+00, 0.000000e+00
  br label %loop.69

loop.69:                                          ; preds = %loop.69, %alloca_0
  %t48.0 = phi double [ 0.000000e+00, %alloca_0 ], [ %5, %loop.69 ]
  %t50.02 = phi double [ 0.000000e+00, %alloca_0 ], [ %3, %loop.69 ]
  %t52.0 = phi double [ 0.000000e+00, %alloca_0 ], [ %7, %loop.69 ]
  %0 = fmul double %t52.0, %mul.3
  %1 = fmul double %t48.0, %mul.4
  %2 = fadd double %1, %0
  %3 = fadd double %2, %c__fetch.3
  %4 = fmul double 0.000000e+00, %mul.3
  %5 = fadd double 0.000000e+00, %4
  %6 = fmul double 0.000000e+00, %mul.4
  %7 = fadd double 0.000000e+00, %6
  br label %loop.69
}
```
author: ivankelarev
body: It appears that the actual problematic commit is the following:

```
commit 66775f8ccdcc8264ef349518e1c59d96d4227823
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Mon Oct 16 12:50:29 2023 -0700

    [SLP]Fix PR69196: Instruction does not dominate all uses
    
    During emission of the postponed gathers, need to insert them before
    user instruction to avoid use before definition crash.
```
For compiler builds prior to this change, the test passes, and the correct code is generated as follows:
```
define void @a_(double %c__fetch.3) {
alloca_0:
  %0 = insertelement <2 x double> <double poison, double 0.000000e+00>, double %c__fetch.3, i32 0
  %1 = fmul <2 x double> zeroinitializer, %0
  %2 = shufflevector <2 x double> %0, <2 x double> <double 0.000000e+00, double poison>, <2 x i32> <i32 2, i32 0>
  %3 = fmul <2 x double> zeroinitializer, %2
  br label %loop.69

loop.69:                                          ; preds = %loop.69, %alloca_0
  %t50.02 = phi double [ 0.000000e+00, %alloca_0 ], [ %9, %loop.69 ]
  %4 = phi <2 x double> [ zeroinitializer, %alloca_0 ], [ %11, %loop.69 ]
  %5 = fmul <2 x double> %4, %3
  %6 = extractelement <2 x double> %5, i32 0
  %7 = extractelement <2 x double> %5, i32 1
  %8 = fadd double %6, %7
  %9 = fadd double %8, %c__fetch.3
  %10 = fmul <2 x double> zeroinitializer, %1
  %11 = fadd <2 x double> zeroinitializer, %10
  br label %loop.69
}
```

Although the commit may seem quite old, there is a test case for which it causes incorrect code generation. Alexey, could you please revisit this change and address the code generation issue for the provided test case?
author: alexey-bataev
body: > It appears that the actual problematic commit is the following:
> 
> ```
> commit 66775f8ccdcc8264ef349518e1c59d96d4227823
> Author: Alexey Bataev <a.bataev@outlook.com>
> Date:   Mon Oct 16 12:50:29 2023 -0700
> 
>     [SLP]Fix PR69196: Instruction does not dominate all uses
>     
>     During emission of the postponed gathers, need to insert them before
>     user instruction to avoid use before definition crash.
> ```
> 
> For compiler builds prior to this change, the test passes, and the correct code is generated as follows:
> 
> ```
> define void @a_(double %c__fetch.3) {
> alloca_0:
>   %0 = insertelement <2 x double> <double poison, double 0.000000e+00>, double %c__fetch.3, i32 0
>   %1 = fmul <2 x double> zeroinitializer, %0
>   %2 = shufflevector <2 x double> %0, <2 x double> <double 0.000000e+00, double poison>, <2 x i32> <i32 2, i32 0>
>   %3 = fmul <2 x double> zeroinitializer, %2
>   br label %loop.69
> 
> loop.69:                                          ; preds = %loop.69, %alloca_0
>   %t50.02 = phi double [ 0.000000e+00, %alloca_0 ], [ %9, %loop.69 ]
>   %4 = phi <2 x double> [ zeroinitializer, %alloca_0 ], [ %11, %loop.69 ]
>   %5 = fmul <2 x double> %4, %3
>   %6 = extractelement <2 x double> %5, i32 0
>   %7 = extractelement <2 x double> %5, i32 1
>   %8 = fadd double %6, %7
>   %9 = fadd double %8, %c__fetch.3
>   %10 = fmul <2 x double> zeroinitializer, %1
>   %11 = fadd <2 x double> zeroinitializer, %10
>   br label %loop.69
> }
> ```
> 
> Although the commit may seem quite old, there is a test case for which it causes incorrect code generation. Alexey, could you please revisit this change and address the code generation issue for the provided test case?

The actual problem is not in this commit, the fix is almost ready

Fix patch:
commit 4a0bbbcbcf6ebc87e794e7b86b9f4651bffcd806
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Fri Aug 16 13:24:03 2024 -0700

    [SLP]Fix PR104637: do not create new nodes for fully overlapped non-schedulable nodes
    
    If the scalars do not require scheduling and were already vectorized,
    but in the different order, compiler still tries to create the new node.
    It may cause the compiler crash for the gathered operands. Instead need
    to consider such nodes as full overlap and just reshuffle vectorized
    node.
    
    Fixes https://github.com/llvm/llvm-project/issues/104637

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 667d0df781aa..9ecd8160a978 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -7144,6 +7144,21 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
                        ReuseShuffleIndices);
         return;
       }
+      SmallPtrSet<const TreeEntry *, 4> Nodes;
+      Nodes.insert(getTreeEntry(S.OpValue));
+      for (const TreeEntry *E : MultiNodeScalars.lookup(S.OpValue))
+        Nodes.insert(E);
+      SmallPtrSet<Value *, 8> Values(VL.begin(), VL.end());
+      if (any_of(Nodes, [&](const TreeEntry *E) {
+            return all_of(E->Scalars,
+                          [&](Value *V) { return Values.contains(V); });
+          })) {
+        LLVM_DEBUG(dbgs() << "SLP: Gathering due to full overlap.\n");
+        if (TryToFindDuplicates(S))
+          newTreeEntry(VL, std::nullopt /*not vectorized*/, S, UserTreeIdx,
+                       ReuseShuffleIndices);
+        return;
+      }
     } else {
       // Record the reuse of the tree node.  FIXME, currently this is only used
       // to properly draw the graph rather than for the actual vectorization.


Regression tests:
file: llvm/test/Transforms/SLPVectorizer/X86/full-non-schedulable-overlap.ll
commands: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu < %s
tests: test_name: test
test_body: define void @test(double %v) {
entry:
  %mul.3 = fmul double 0.000000e+00, %v
  %mul.4 = fmul double 0.000000e+00, 0.000000e+00
  br label %loop

loop:                                             ; preds = %loop, %entry
  %t48.0 = phi double [ 0.000000e+00, %entry ], [ %5, %loop ]
  %t50.02 = phi double [ 0.000000e+00, %entry ], [ %3, %loop ]
  %t52.0 = phi double [ 0.000000e+00, %entry ], [ %7, %loop ]
  %0 = fmul double %t52.0, %mul.3
  %1 = fmul double %t48.0, %mul.4
  %2 = fadd double %1, %0
  %3 = fadd double %2, %v
  %4 = fmul double 0.000000e+00, %mul.3
  %5 = fadd double 0.000000e+00, %4
  %6 = fmul double 0.000000e+00, %mul.4
  %7 = fadd double 0.000000e+00, %6
  br label %loop
}