Bug type: crash
Component: VectorCombine
Bug location: llvm/lib/Transforms/Vectorize/VectorCombine.cpp: VectorCombine::foldSelectsFromBitcast
Issue title: [VectorCombine] LLVM ERROR: Broken module found, compilation aborted!
Labels: crash-on-valid
generated by fuzzer
llvm::vectorcombine
Reported by: XChy

Reproducer: https://godbolt.org/z/nWG51fEc1
Testcase:
```llvm
define i8 @backsmith_pure_0() {
entry:
  %0 = bitcast <4 x i64> splat (i64 1) to <32 x i8>
  %vecext56 = extractelement <32 x i8> %0, i64 0
  %tobool.not = icmp eq i8 0, 0
  %vecext36 = extractelement <32 x i8> %0, i64 0
  %narrow = select i1 %tobool.not, i8 %vecext36, i8 0
  %narrow8 = select i1 %tobool.not, i8 %vecext56, i8 0
  ret i8 %narrow8
}
```

Dump:
```
Instruction does not dominate all uses!
  %tobool.not = icmp eq i8 0, 0
  %0 = select i1 %tobool.not, <4 x i64> splat (i64 1), <4 x i64> zeroinitializer
LLVM ERROR: Broken module found, compilation aborted!
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and instructions to reproduce the bug.
Stack dump:
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/opt -o /app/output.s -S --passes=vector-combine <source>
1.	Running pass "verify" on module "<source>"
 #0 0x0000000005a91978 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x5a91978)
 #1 0x0000000005a8e854 SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
 #2 0x000074e865242520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x000074e8652969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x000074e865242476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x000074e8652287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x000000000082b993 llvm::json::operator==(llvm::json::Value const&, llvm::json::Value const&) (.cold) JSON.cpp:0:0
 #7 0x00000000059c3d61 (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x59c3d61)
 #8 0x0000000005847298 (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x5847298)
 #9 0x0000000000962fde llvm::detail::PassModel<llvm::Module, llvm::VerifierPass, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x962fde)
#10 0x00000000058035e1 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x58035e1)
#11 0x000000000096d1ca llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::ArrayRef<std::function<void (llvm::PassBuilder&)>>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x96d1ca)
#12 0x0000000000961278 optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x961278)
#13 0x000074e865229d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#14 0x000074e865229e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#15 0x0000000000957ef5 _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x957ef5)
Program terminated with signal: SIGSEGV
Compiler returned: 139
```

Comments: author: RKSimon
body: ```
VECTORCOMBINE on backsmith_pure_0
VC: Visiting:   %0 = bitcast <4 x i64> splat (i64 1) to <32 x i8>
VC: Replacing:   %narrow = select i1 %tobool.not, i8 %vecext36, i8 0
         With:   %3 = extractelement <32 x i8> %2, i64 0
ADD:   %narrow = extractelement <32 x i8> %2, i64 0
VC: Erasing:   %3 = select i1 %tobool.not, i8 %vecext36, i8 0
ADD:   %1 = select i1 %tobool.not, <4 x i64> splat (i64 1), <4 x i64> zeroinitializer
ADD:   %narrow8 = select i1 %tobool.not, i8 %vecext56, i8 0
ADD:   %tobool.not = icmp eq i8 0, 0
VC: Erased:   %vecext36 = extractelement <32 x i8> %0, i64 0
VC: Replacing:   %narrow8 = select i1 %tobool.not, i8 %vecext56, i8 0
         With:   %3 = extractelement <32 x i8> %2, i64 0
ADD:   ret i8 %narrow8
ADD:   %narrow8 = extractelement <32 x i8> %2, i64 0
VC: Erasing:   %3 = select i1 %tobool.not, i8 %vecext56, i8 0
VC: Erased:   %vecext56 = extractelement <32 x i8> %0, i64 0
VC: Erased:   %0 = bitcast <4 x i64> splat (i64 1) to <32 x i8>
VectorCombine: folded 2 selects into vector select
VC: Visiting:   %tobool.not = icmp eq i8 0, 0
VC: Visiting:   %narrow = extractelement <32 x i8> %1, i64 0
VC: Visiting:   %narrow8 = extractelement <32 x i8> %1, i64 0
VC: Visiting:   ret i8 %narrow8
VC: Visiting:   %narrow8 = extractelement <32 x i8> %1, i64 0
VC: Visiting:   ret i8 %narrow8
VC: Visiting:   %tobool.not = icmp eq i8 0, 0
VC: Visiting:   %0 = select i1 %tobool.not, <4 x i64> splat (i64 1), <4 x i64> zeroinitializer
VC: Erasing:   %narrow = extractelement <32 x i8> %1, i64 0
ADD:   %narrow8 = extractelement <32 x i8> %1, i64 0
ADD:   %1 = bitcast <4 x i64> %0 to <32 x i8>
VC: Visiting:   %1 = bitcast <4 x i64> %0 to <32 x i8>
VC: Visiting:   %narrow8 = extractelement <32 x i8> %1, i64 0
Instruction does not dominate all uses!
  %tobool.not = icmp eq i8 0, 0
  %0 = select i1 %tobool.not, <4 x i64> splat (i64 1), <4 x i64> zeroinitializer
```

Fix patch:
commit 4ec35a0b0e13f15ad38a2fa668004c892a365795
Author: Mitch Briles <mitchbriles@gmail.com>
Date:   Wed Jan 28 08:13:50 2026 -0700

    [VectorCombine] Fix crash when folding select of bitcast (#177183)
    
    Fixes #177144. Nits appreciated.
    
    The fold in question does the following transformation:
    Before
    ```
    %bc = bitcast <4 x i32> %src to <16 x i8>
    %e0 = extractelement <16 x i8> %bc, i32 0
    %s0 = select i1 %cond, i8 %e0, i8 0
    %e1 = extractelement <16 x i8> %bc, i32 1
    %s1 = select i1 %cond, i8 %e1, i8 0
    ...
    ```
    
    After
    ```
    %sel = select i1 %cond, <4 x i32> %src, <4 x i32> zeroinitializer
    %bc = bitcast <4 x i32> %sel to <16 x i8>
    %e0 = extractelement <16 x i8> %bc, i32 0
    %e1 = extractelement <16 x i8> %bc, i32 1
    ...
    ```
    If every select shares the condition and has 0 in the false branch, the
    bitcast can be replaced with a select between the original vector and
    `zeroinitializer`, followed by a bitcast. Then each `select(cond,
    extelt(...), 0)` can be replaced with `extelt(...)`.
    The crash happens when the condition is defined after the original
    bitcast, because the bitcast is replaced with the select + bitcast, and
    now the select references a condition not yet defined.

diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
index fbb3b820c4f0..fb6fa247038a 100644
--- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
+++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
@@ -1655,7 +1655,13 @@ bool VectorCombine::foldSelectsFromBitcast(Instruction &I) {
     }
 
     // Create the vector select and bitcast once for this condition.
-    Builder.SetInsertPoint(BC->getNextNode());
+    auto InsertPt = std::next(BC->getIterator());
+
+    if (auto *CondInst = dyn_cast<Instruction>(Cond))
+      if (DT.dominates(BC, CondInst))
+        InsertPt = std::next(CondInst->getIterator());
+
+    Builder.SetInsertPoint(InsertPt);
     Value *VecSel =
         Builder.CreateSelect(Cond, SrcVec, Constant::getNullValue(SrcVecTy));
     Value *NewBC = Builder.CreateBitCast(VecSel, DstVecTy);


Regression tests:
file: llvm/test/Transforms/VectorCombine/AMDGPU/combine-scalar-selects.ll
commands: opt -mtriple=amdgcn-amd-amdhsa -mcpu=gfx942 -passes=vector-combine -S %s
opt -mtriple=amdgcn-amd-amdhsa -mcpu=gfx942 -S %s
tests: test_name: fold_selects_from_bitcast_dominance_multiblock2
test_body: define i8 @fold_selects_from_bitcast_dominance_multiblock2(<4 x i64> %v, i8 %a, i1 %flag) {
entry:
  %0 = bitcast <4 x i64> %v to <32 x i8>
  br label %first

first:                                            ; preds = %entry
  %vecext1 = extractelement <32 x i8> %0, i64 0
  %vecext2 = extractelement <32 x i8> %0, i64 7
  %vecext3 = extractelement <32 x i8> %0, i64 1
  %vecext4 = extractelement <32 x i8> %0, i64 8
  %vecext5 = extractelement <32 x i8> %0, i64 9
  br label %second

second:                                           ; preds = %first
  %cond = icmp eq i8 %a, 0
  br i1 %flag, label %then, label %else

then:                                             ; preds = %second
  %s1 = select i1 %cond, i8 %vecext1, i8 0
  br label %combine

else:                                             ; preds = %second
  %s2 = select i1 %cond, i8 %vecext2, i8 0
  br label %combine

combine:                                          ; preds = %else, %then
  %r1 = phi i8 [ %s1, %then ], [ %s2, %else ]
  %s3 = select i1 %cond, i8 %vecext3, i8 0
  %s4 = select i1 %cond, i8 %vecext4, i8 0
  %s5 = select i1 %cond, i8 %vecext5, i8 0
  %r2 = add i8 %r1, %s3
  %r3 = add i8 %r2, %s4
  %r4 = add i8 %r3, %s5
  ret i8 %r4
}

test_name: fold_selects_from_bitcast_dominance_multiblock3
test_body: define i8 @fold_selects_from_bitcast_dominance_multiblock3(<4 x i64> %v1, <4 x i64> %v2, i8 %a, i1 %flag1, i1 %flag2, i1 %flag3, i1 %flag4, i1 %cond2) {
entry:
  %0 = bitcast <4 x i64> %v1 to <32 x i8>
  %1 = bitcast <4 x i64> %v2 to <32 x i8>
  br label %first

first:                                            ; preds = %entry
  %vecext00 = extractelement <32 x i8> %0, i64 0
  %vecext02 = extractelement <32 x i8> %0, i64 2
  %vecext04 = extractelement <32 x i8> %0, i64 4
  %vecext06 = extractelement <32 x i8> %0, i64 6
  %vecext08 = extractelement <32 x i8> %0, i64 8
  %vecext11 = extractelement <32 x i8> %1, i64 1
  %vecext13 = extractelement <32 x i8> %1, i64 3
  %vecext15 = extractelement <32 x i8> %1, i64 5
  %vecext17 = extractelement <32 x i8> %1, i64 7
  %vecext19 = extractelement <32 x i8> %1, i64 9
  br label %t0

t0:                                               ; preds = %first
  %cond1 = icmp eq i8 %a, 0
  br i1 %flag1, label %r0, label %t1

t1:                                               ; preds = %t0
  br i1 %flag2, label %r1, label %t2

t2:                                               ; preds = %t1
  br i1 %flag3, label %r2, label %t3

t3:                                               ; preds = %t2
  br i1 %flag4, label %r3, label %r4

r0:                                               ; preds = %t0
  %res0 = select i1 %cond1, i8 %vecext00, i8 0
  %res1 = select i1 %cond2, i8 %vecext11, i8 0
  %res01 = add i8 %res0, %res1
  ret i8 %res01

r1:                                               ; preds = %t1
  %res2 = select i1 %cond1, i8 %vecext02, i8 0
  %res3 = select i1 %cond2, i8 %vecext13, i8 0
  %res23 = add i8 %res2, %res3
  ret i8 %res23

r2:                                               ; preds = %t2
  %res4 = select i1 %cond1, i8 %vecext04, i8 0
  %res5 = select i1 %cond2, i8 %vecext15, i8 0
  %res45 = add i8 %res4, %res5
  ret i8 %res45

r3:                                               ; preds = %t3
  %res6 = select i1 %cond1, i8 %vecext06, i8 0
  %res7 = select i1 %cond2, i8 %vecext17, i8 0
  %res67 = add i8 %res6, %res7
  ret i8 %res67

r4:                                               ; preds = %t3
  %res8 = select i1 %cond1, i8 %vecext08, i8 0
  %res9 = select i1 %cond2, i8 %vecext19, i8 0
  %res89 = add i8 %res8, %res9
  ret i8 %res89
}

test_name: fold_selects_from_bitcast_dominance_multiblock1
test_body: define i8 @fold_selects_from_bitcast_dominance_multiblock1(<4 x i32> %src, i8 %a, i1 %flag1, i1 %flag2) {
  %bc = bitcast <4 x i32> %src to <16 x i8>
  %cond = icmp eq i8 %a, 0
  br i1 %flag1, label %first, label %trampoline

trampoline:                                       ; preds = %0
  br i1 %flag2, label %second, label %third

first:                                            ; preds = %0
  %e00 = extractelement <16 x i8> %bc, i32 0
  %s00 = select i1 %cond, i8 %e00, i8 0
  %e01 = extractelement <16 x i8> %bc, i32 2
  %s01 = select i1 %cond, i8 %e01, i8 0
  %s0 = add i8 %s00, %s01
  br label %end

second:                                           ; preds = %trampoline
  %e10 = extractelement <16 x i8> %bc, i32 3
  %s10 = select i1 %cond, i8 %e10, i8 0
  %e11 = extractelement <16 x i8> %bc, i32 4
  %s11 = select i1 %cond, i8 %e11, i8 0
  %s1 = add i8 %s10, %s11
  br label %end

third:                                            ; preds = %trampoline
  %e20 = extractelement <16 x i8> %bc, i32 5
  %s20 = select i1 %cond, i8 %e20, i8 0
  %e21 = extractelement <16 x i8> %bc, i32 6
  %s21 = select i1 %cond, i8 %e21, i8 0
  %s2 = add i8 %s20, %s21
  br label %end

end:                                              ; preds = %third, %second, %first
  %res = phi i8 [ %s0, %first ], [ %s1, %second ], [ %s2, %third ]
  ret i8 %res
}