commit d2e7ee77d33e8b3be3b1d4e9bc5bc4c60b62b554
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Thu Oct 24 08:15:21 2024 -0700

    [SLP]Do not check for clustered loads only

    Since SLP support "clusterization" of the non-load instructions, the
    restriction for reduced values for loads only should be removed to avoid
    compiler crash.

    Fixes #113516

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index f76e913a57d5..012d85353f08 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -16118,7 +16118,7 @@ BoUpSLP::vectorizeTree(const ExtraValueToDebugLocsMap &ExternallyUsedValues,
     for (Instruction *I : RemovedInsts) {
       const TreeEntry *IE = getTreeEntry(I);
       if (IE->Idx != 0 &&
-          !(VectorizableTree.front()->isGather() && isa<LoadInst>(I) &&
+          !(VectorizableTree.front()->isGather() &&
             !IE->UserTreeIndices.empty() &&
             any_of(IE->UserTreeIndices,
                    [&](const EdgeInfo &EI) {

[SLPVectorizer] Assertion `(I->use_empty() || all_of(I->uses(), [&](Use &U) { return isDeleted( cast<Instruction>(U.getUser())); })) && "trying to erase instruction with users."' failed.

Reduced reproducer: https://godbolt.org/z/azEc6zjod
```
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 i1 @foo() {
entry:
  %tobool.not.not509.i.1311.i.i = icmp ne i32 0, 0
  %cmp80.1319.i.i189 = icmp sgt i32 0, 0
  %tobool.not.not509.i.1.1.i.i = icmp ne i32 0, 0
  %cmp80.1.1.i.i190 = icmp sgt i32 0, 0
  %tobool.not.not509.i.2329.i.i = icmp ne i32 0, 0
  %storemerge.2333.i.i = select i1 %tobool.not.not509.i.2329.i.i, i32 0, i32 0
  %cmp80.2337.i.i192 = icmp sgt i32 0, 0
  %tobool.not.not509.i.1.2.i.i = icmp ne i32 %storemerge.2333.i.i, 0
  %cmp80.1.2.i.i193 = icmp sgt i32 0, 0
  %cmp80.1.2.i.i = select i1 %tobool.not.not509.i.1.2.i.i, i1 %cmp80.1.2.i.i193, i1 false
  %0 = select i1 %cmp80.1.2.i.i, i1 %tobool.not.not509.i.2329.i.i, i1 false
  %1 = select i1 %0, i1 %cmp80.2337.i.i192, i1 false
  %2 = select i1 %1, i1 false, i1 false
  %3 = select i1 %2, i1 %tobool.not.not509.i.1.1.i.i, i1 false
  %4 = select i1 %3, i1 %cmp80.1.1.i.i190, i1 false
  %5 = select i1 %4, i1 %tobool.not.not509.i.1311.i.i, i1 false
  %6 = select i1 %5, i1 %cmp80.1319.i.i189, i1 false
  ret i1 %6
}
```
```
opt: /root/llvm-project/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp:2748: void llvm::slpvectorizer::BoUpSLP::removeInstructionsAndOperands(llvm::ArrayRef<U*>) [with T = llvm::Instruction]: Assertion `(I->use_empty() || all_of(I->uses(), [&](Use &U) { return isDeleted( cast<Instruction>(U.getUser())); })) && "trying to erase instruction with users."' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/opt -o /app/output.s -S -passes=slp-vectorizer <source>
1.	Running pass "function(slp-vectorizer)" on module "<source>"
2.	Running pass "slp-vectorizer" on function "foo"
 #0 0x00000000050d8608 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x50d8608)
 #1 0x00000000050d5fbc SignalHandler(int) Signals.cpp:0:0
 #2 0x000071afd7642520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x000071afd76969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x000071afd7642476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x000071afd76287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x000071afd762871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
 #7 0x000071afd7639e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
 #8 0x000000000414e3af void llvm::slpvectorizer::BoUpSLP::removeInstructionsAndOperands<llvm::Instruction>(llvm::ArrayRef<llvm::Instruction*>) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x414e3af)
 #9 0x00000000041aa335 llvm::slpvectorizer::BoUpSLP::vectorizeTree(llvm::SmallDenseSet<llvm::Value*, 4u, llvm::DenseMapInfo<llvm::Value*, void>> const&, llvm::Instruction*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x41aa335)
#10 0x00000000041bcd90 (anonymous namespace)::HorizontalReduction::tryToReduce(llvm::slpvectorizer::BoUpSLP&, llvm::DataLayout const&, llvm::TargetTransformInfo*, llvm::TargetLibraryInfo const&) SLPVectorizer.cpp:0:0
#11 0x00000000041bfb71 llvm::SLPVectorizerPass::vectorizeHorReduction(llvm::PHINode*, llvm::Instruction*, llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&, llvm::SmallVectorImpl<llvm::WeakTrackingVH>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x41bfb71)
#12 0x00000000041c431b llvm::SLPVectorizerPass::vectorizeRootInstruction(llvm::PHINode*, llvm::Instruction*, llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&) (.constprop.0) SLPVectorizer.cpp:0:0
#13 0x00000000041c8ae8 llvm::SLPVectorizerPass::vectorizeChainsInBlock(llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x41c8ae8)
#14 0x00000000041cf231 llvm::SLPVectorizerPass::runImpl(llvm::Function&, llvm::ScalarEvolution*, llvm::TargetTransformInfo*, llvm::TargetLibraryInfo*, llvm::AAResults*, llvm::LoopInfo*, llvm::DominatorTree*, llvm::AssumptionCache*, llvm::DemandedBits*, llvm::OptimizationRemarkEmitter*) (.part.0) SLPVectorizer.cpp:0:0
#15 0x00000000041cfedb llvm::SLPVectorizerPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x41cfedb)
#16 0x0000000002f64f0e llvm::detail::PassModel<llvm::Function, llvm::SLPVectorizerPass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x2f64f0e)
#17 0x0000000004ed9788 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4ed9788)
#18 0x0000000000e2773e llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xe2773e)
#19 0x0000000004ed81ae llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4ed81ae)
#20 0x0000000000e26e8e llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xe26e8e)
#21 0x0000000004ed7be0 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4ed7be0)
#22 0x000000000090a07a 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) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x90a07a)
#23 0x00000000008fce7c optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8fce7c)
#24 0x000071afd7629d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#25 0x000071afd7629e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#26 0x00000000008f493e _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8f493e)
Program terminated with signal: SIGSEGV
Compiler returned: 139
```
llvm version: 33363521ca24f912cc25530f6cecbca53acce8a3


commit e3c537ff903af9a92ff43bab6d21c0ea759d65e5
Author: Florian Hahn <flo@fhahn.com>
Date:   Tue Sep 10 21:37:12 2024 +0100

    [VPlan] Consider non-header phis in planContainsAdditionalSimp.

    Update planContainsAdditionalSimplifications to also check phis not in
    the loop header. This ensures we don't miss cases where VPBlendRecipes
    (which correspond to such phis) have been simplified.

    Fixes https://github.com/llvm/llvm-project/issues/107473.

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 2be3b5775292..b821da03c16e 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -7314,9 +7314,10 @@ static bool planContainsAdditionalSimplifications(VPlan &Plan,
   // Return true if the loop contains any instructions that are not also part of
   // the VPlan or are skipped for VPlan-based cost computations. This indicates
   // that the VPlan contains extra simplifications.
-  return any_of(TheLoop->blocks(), [&SeenInstrs, &CostCtx](BasicBlock *BB) {
-    return any_of(*BB, [&SeenInstrs, &CostCtx](Instruction &I) {
-      if (isa<PHINode>(&I))
+  return any_of(TheLoop->blocks(), [&SeenInstrs, &CostCtx,
+                                    TheLoop](BasicBlock *BB) {
+    return any_of(*BB, [&SeenInstrs, &CostCtx, TheLoop, BB](Instruction &I) {
+      if (isa<PHINode>(&I) && BB == TheLoop->getHeader())
         return false;
       return !SeenInstrs.contains(&I) && !CostCtx.skipCostComputation(&I, true);
     });

opt -p loop-vectorize -mtriple riscv64-linux-gnu -mattr=+v,+f -S %s

target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"

define void @dead_load(ptr %p, i16 %start) {
entry:
  %start.ext = sext i16 %start to i64
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ %start.ext, %entry ], [ %iv.next, %loop ]
  %gep = getelementptr i16, ptr %p, i64 %iv
  store i16 0, ptr %gep, align 2
  %l = load i16, ptr %gep, align 2
  %iv.next = add i64 %iv, 3
  %cmp = icmp slt i64 %iv, 111
  br i1 %cmp, label %loop, label %exit

exit:                                             ; preds = %loop
  ret void
}

target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"

define i8 @dead_live_out_due_to_scalar_epilogue_required(ptr %src, ptr %dst) {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
  %idxprom = sext i32 %iv to i64
  %gep.src = getelementptr i8, ptr %src, i64 %idxprom
  %l = load i8, ptr %gep.src, align 1
  %gep.dst = getelementptr i8, ptr %dst, i64 %idxprom
  store i8 0, ptr %gep.dst, align 1
  %iv.next = add i32 %iv, 4
  %cmp = icmp ult i32 %iv, 1001
  br i1 %cmp, label %loop, label %exit

exit:                                             ; preds = %loop
  %r = phi i8 [ %l, %loop ]
  ret i8 %r
}

target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"

define void @test_phi_in_latch_redundant(ptr %dst, i32 %a) {
entry:
  br label %loop.header

loop.header:                                      ; preds = %loop.latch, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  br i1 false, label %loop.latch, label %then

then:                                             ; preds = %loop.header
  %not.a = xor i32 %a, -1
  br label %loop.latch

loop.latch:                                       ; preds = %then, %loop.header
  %p = phi i32 [ %not.a, %then ], [ 0, %loop.header ]
  %gep = getelementptr i32, ptr %dst, i64 %iv
  store i32 %p, ptr %gep, align 4
  %iv.next = add i64 %iv, 9
  %ec = icmp slt i64 %iv, 322
  br i1 %ec, label %loop.header, label %exit

exit:                                             ; preds = %loop.latch
  ret void
}

target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i16 @llvm.umax.i16(i16, i16) #0

define i32 @cost_of_exit_branch_and_cond_insts(ptr %a, ptr %b, i1 %c, i16 %x) {
entry:
  br label %loop.header

loop.header:                                      ; preds = %loop.latch, %entry
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  br i1 %c, label %then, label %loop.exiting

then:                                             ; preds = %loop.header
  %gep = getelementptr inbounds i32, ptr %b, i32 %iv
  store i1 false, ptr %a, align 1
  store i32 0, ptr %gep, align 4
  br label %loop.exiting

loop.exiting:                                     ; preds = %then, %loop.header
  %iv.next = add i32 %iv, 1
  %umax = tail call i16 @llvm.umax.i16(i16 %x, i16 111)
  %umax.ext = zext i16 %umax to i32
  %sub = sub i32 770, %umax.ext
  %ec = icmp slt i32 %iv, %sub
  br i1 %ec, label %loop.latch, label %exit

loop.latch:                                       ; preds = %loop.exiting
  br label %loop.header

exit:                                             ; preds = %loop.exiting
  br label %return

return:                                           ; preds = %exit
  ret i32 0
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

[VPlan] Assertion " VPlan cost model and legacy cost model disagreed"' failed.

Testing using 0c1500ef05e0a5b25cae79d2bd361dbc6e14e726

C testcase:
```
int a;
extern int b[][3][3][3][3][3];
_Bool c;
unsigned char d[1][13][13];
unsigned e[1][13][13][13];
int f[6];
unsigned short g[1][13][13][13];
unsigned h[1][13][13], i[1][13][13];
short j[1][13][13];
unsigned k[3][13][13];
unsigned short l[1][13];
short m[1][13];
unsigned short n[1][13][13];
unsigned o[1][13];
void p(char q, int r, char s, unsigned char z[][13][13],
       unsigned aa[][13][13][13], int ab[], unsigned short ac[][13][13][13],
       unsigned ad[][13][13], short ae[][13][13], unsigned af[][13][13],
       unsigned short ag[][13], short ah[][13], unsigned short ai[][13][13],
       unsigned aj[][13][13], unsigned ak[][13]) {
  for (unsigned t = 0; t < q; t += 50)
    for (unsigned u = 0; u < 2; u = 6)
      for (short w = 0; w < 2; w += 42155)
        for (signed x = -15; x < r; x += s) {
          b[x][x][u][2][x][2] = ab[5] ? ~af[2][1][x] : 0;
          a = x ? c ? aj[2][u][x] : 0 : ae[2][w][4];
        }
}
int main() {
  f[5] = 8;
  for (long t = 0; t < 3; ++t)
    for (long v = 0; v < 3; ++v)
      for (long y = 0; y < 3; ++y)
        k[t][v][y] = 3004284279;
  p(8, 322, 9, d, e, f, g, h, j, k, l, m, n, i, o);
}
```

LLVM IR:
```llvm ir
; ModuleID = 'reduced.bc'
target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "riscv64-unknown-linux-gnu"

define i32 @main(i64 %indvars.iv) #0 {
entry:
  br label %for.body17.us77.us.us.i

for.body17.us77.us.us.i:                          ; preds = %cond.end.us84.us.us.i, %entry
  %indvars.iv1 = phi i64 [ %indvars.iv.next, %cond.end.us84.us.us.i ], [ 0, %entry ]
  br i1 false, label %cond.end.us84.us.us.i, label %cond.true.us80.us.us.i

cond.true.us80.us.us.i:                           ; preds = %for.body17.us77.us.us.i
  %not.us83.us.us.i = xor i32 0, 0
  br label %cond.end.us84.us.us.i

cond.end.us84.us.us.i:                            ; preds = %cond.true.us80.us.us.i, %for.body17.us77.us.us.i
  %cond.us85.us.us.i = phi i32 [ %not.us83.us.us.i, %cond.true.us80.us.us.i ], [ 0, %for.body17.us77.us.us.i ]
  %arrayidx30.us87.us.us.i = getelementptr [0 x [3 x [3 x [3 x [3 x [3 x i32]]]]]], ptr null, i64 0, i64 %indvars.iv1, i64 %indvars.iv, i64 0, i64 2, i64 %indvars.iv, i64 2
  store i32 %cond.us85.us.us.i, ptr %arrayidx30.us87.us.us.i, align 4
  %indvars.iv.next = add i64 %indvars.iv1, 9
  %cmp14.us95.us.us.i = icmp slt i64 %indvars.iv1, 322
  br i1 %cmp14.us95.us.us.i, label %for.body17.us77.us.us.i, label %for.body17.us77.us.us.1.i.preheader

for.body17.us77.us.us.1.i.preheader:              ; preds = %cond.end.us84.us.us.i
  ret i32 0
}

attributes #0 = { "target-features"="+64bit,+a,+c,+d,+f,+m,+relax,+v,+zicsr,+zifencei,+zmmul,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b,-b,-e,-experimental-smctr,-experimental-smmpm,-experimental-smnpm,-experimental-ssctr,-experimental-ssnpm,-experimental-sspm,-experimental-supm,-experimental-zacas,-experimental-zalasr,-experimental-zicfilp,-experimental-zicfiss,-experimental-zvbc32e,-experimental-zvkgs,-h,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smcdeleg,-smcsrind,-smepmp,-smstateen,-ssaia,-ssccfg,-ssccptr,-sscofpmf,-sscounterenw,-sscsrind,-ssqosid,-ssstateen,-ssstrict,-sstc,-sstvala,-sstvecd,-ssu64xl,-svade,-svadu,-svbare,-svinval,-svnapot,-svpbmt,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xsfcease,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xsifivecdiscarddlone,-xsifivecflushdlone,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-xwchc,-za128rs,-za64rs,-zaamo,-zabha,-zalrsc,-zama16b,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmop,-zcmp,-zcmt,-zdinx,-zfa,-zfbfmin,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zihintntl,-zihintpause,-zihpm,-zimop,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-ztso,-zvbb,-zvbc,-zvfbfmin,-zvfbfwma,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl4096b,-zvl512b,-zvl65536b,-zvl8192b" }
```

Command/backtrace:
```
> /scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt -passes=loop-vectorize reduced.ll -S
opt: /scratch/tc-testing/tc-compiler-fuzz-trunk/llvm/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:7400: llvm::VectorizationFactor llvm::LoopVectorizationPlanner::computeBestVF(): Assertion `(BestFactor.Width == LegacyVF.Width || planContainsAdditionalSimplifications(getPlanFor(BestFactor.Width), CostCtx, OrigLoop)) && " VPlan cost model and legacy cost model disagreed"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: /scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt -passes=loop-vectorize reduced.ll -S
1.      Running pass "function(loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>)" on module "reduced.ll"
2.      Running pass "loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>" on function "main"
 #0 0x000059162be7f6e0 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x30136e0)
 #1 0x000059162be7caef llvm::sys::RunSignalHandlers() (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x3010aef)
 #2 0x000059162be7cc45 SignalHandler(int) Signals.cpp:0:0
 #3 0x00007152dd642520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #4 0x00007152dd6969fc __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #5 0x00007152dd6969fc __pthread_kill_internal ./nptl/pthread_kill.c:78:10
 #6 0x00007152dd6969fc pthread_kill ./nptl/pthread_kill.c:89:10
 #7 0x00007152dd642476 gsignal ./signal/../sysdeps/posix/raise.c:27:6
 #8 0x00007152dd6287f3 abort ./stdlib/abort.c:81:7
 #9 0x00007152dd62871b _nl_load_domain ./intl/loadmsgcat.c:1177:9
#10 0x00007152dd639e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
#11 0x000059162ae52310 llvm::LoopVectorizationPlanner::computeBestVF() (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x1fe6310)
#12 0x000059162ae6910b llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x1ffd10b)
#13 0x000059162ae6c121 llvm::LoopVectorizePass::runImpl(llvm::Function&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2000121)
#14 0x000059162ae6c797 llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2000797)
#15 0x0000591629cc8756 llvm::detail::PassModel<llvm::Function, llvm::LoopVectorizePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0xe5c756)
#16 0x000059162bc8b67f llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2e1f67f)
#17 0x0000591629ccb8e6 llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0xe5f8e6)
#18 0x000059162bc89a1b llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2e1da1b)
#19 0x0000591629cc7b36 llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0xe5bb36)
#20 0x000059162bc8a57d llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2e1e57d)
#21 0x00005916294f41b6 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) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x6881b6)
#22 0x00005916294e5f11 optMain (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x679f11)
#23 0x00007152dd629d90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#24 0x00007152dd629e40 call_init ./csu/../csu/libc-start.c:128:20
#25 0x00007152dd629e40 __libc_start_main ./csu/../csu/libc-start.c:379:5
#26 0x00005916294dc2c5 _start (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x6702c5)
zsh: IOT instruction (core dumped)  /scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt
```
https://godbolt.org/z/qEEqe1exM

Found via fuzzer

Related/prior issue: https://github.com/llvm/llvm-project/issues/107171

cc @fhahn

Ping. The C fuzzer is hitting this assertion ~15 times a day since the runs starting sep 6th.


commit 46e04f7fe5c0f01ba452489bb966bdf2d560a63d
Author: Nikita Popov <npopov@redhat.com>
Date:   Mon Dec 9 12:21:49 2024 +0100

    [MemorySSA] Handle MemoryDef optimized away during cloning (#117883)

    When determining the replacement access during cloning, we currently
    leave accesses for instructions that are not in the VMap alone. This is
    correct if the instruction is not in VMap because it hasn't been cloned,
    but not if it has been cloned and then removed. In that case, we should
    walk up to the defining access, like in other simplification cases.

    To distinguish the two cases, pass in a callback that queries whether
    the instruction is part of the cloned region.

    An alternative to this would be to delay removal of dead instructions in
    SimpleLoopUnswitch until after MSSA cloning.

    Fixes https://github.com/llvm/llvm-project/issues/116228.

diff --git a/llvm/include/llvm/Analysis/MemorySSAUpdater.h b/llvm/include/llvm/Analysis/MemorySSAUpdater.h
index 055feceefb05..b8e08f4b7842 100644
--- a/llvm/include/llvm/Analysis/MemorySSAUpdater.h
+++ b/llvm/include/llvm/Analysis/MemorySSAUpdater.h
@@ -260,23 +260,32 @@ private:
   MemoryAccess *tryRemoveTrivialPhi(MemoryPhi *Phi, RangeType &Operands);
   void tryRemoveTrivialPhis(ArrayRef<WeakVH> UpdatedPHIs);
   void fixupDefs(const SmallVectorImpl<WeakVH> &);
-  // Clone all uses and defs from BB to NewBB given a 1:1 map of all
-  // instructions and blocks cloned, and a map of MemoryPhi : Definition
-  // (MemoryAccess Phi or Def). VMap maps old instructions to cloned
-  // instructions and old blocks to cloned blocks. MPhiMap, is created in the
-  // caller of this private method, and maps existing MemoryPhis to new
-  // definitions that new MemoryAccesses must point to. These definitions may
-  // not necessarily be MemoryPhis themselves, they may be MemoryDefs. As such,
-  // the map is between MemoryPhis and MemoryAccesses, where the MemoryAccesses
-  // may be MemoryPhis or MemoryDefs and not MemoryUses.
-  // If CloneWasSimplified = true, the clone was exact. Otherwise, assume that
-  // the clone involved simplifications that may have: (1) turned a MemoryUse
-  // into an instruction that MemorySSA has no representation for, or (2) turned
-  // a MemoryDef into a MemoryUse or an instruction that MemorySSA has no
-  // representation for. No other cases are supported.
+  /// Clone all uses and defs from BB to NewBB given a 1:1 map of all
+  /// instructions and blocks cloned, and a map of MemoryPhi : Definition
+  /// (MemoryAccess Phi or Def).
+  ///
+  /// \param VMap Maps old instructions to cloned instructions and old blocks
+  ///        to cloned blocks
+  /// \param MPhiMap, is created in the caller of this private method, and maps
+  ///        existing MemoryPhis to new definitions that new MemoryAccesses
+  ///        must point to. These definitions may not necessarily be MemoryPhis
+  ///        themselves, they may be MemoryDefs. As such, the map is between
+  ///        MemoryPhis and MemoryAccesses, where the MemoryAccesses may be
+  ///        MemoryPhis or MemoryDefs and not MemoryUses.
+  /// \param IsInClonedRegion Determines whether a basic block was cloned.
+  ///        References to accesses outside the cloned region will not be
+  ///        remapped.
+  /// \param CloneWasSimplified If false, the clone was exact. Otherwise,
+  ///        assume that the clone involved simplifications that may have:
+  ///        (1) turned a MemoryUse into an instruction that MemorySSA has no
+  ///        representation for, or (2) turned a MemoryDef into a MemoryUse or
+  ///        an instruction that MemorySSA has no representation for. No other
+  ///        cases are supported.
   void cloneUsesAndDefs(BasicBlock *BB, BasicBlock *NewBB,
                         const ValueToValueMapTy &VMap, PhiToDefMap &MPhiMap,
+                        function_ref<bool(BasicBlock *)> IsInClonedRegion,
                         bool CloneWasSimplified = false);
+
   template <typename Iter>
   void privateUpdateExitBlocksForClonedLoop(ArrayRef<BasicBlock *> ExitBlocks,
                                             Iter ValuesBegin, Iter ValuesEnd,
diff --git a/llvm/lib/Analysis/MemorySSAUpdater.cpp b/llvm/lib/Analysis/MemorySSAUpdater.cpp
index f672bd0e1e13..050b827388d3 100644
--- a/llvm/lib/Analysis/MemorySSAUpdater.cpp
+++ b/llvm/lib/Analysis/MemorySSAUpdater.cpp
@@ -565,24 +565,26 @@ static MemoryAccess *onlySingleValue(MemoryPhi *MP) {
   return MA;
 }

-static MemoryAccess *getNewDefiningAccessForClone(MemoryAccess *MA,
-                                                  const ValueToValueMapTy &VMap,
-                                                  PhiToDefMap &MPhiMap,
-                                                  MemorySSA *MSSA) {
+static MemoryAccess *getNewDefiningAccessForClone(
+    MemoryAccess *MA, const ValueToValueMapTy &VMap, PhiToDefMap &MPhiMap,
+    MemorySSA *MSSA, function_ref<bool(BasicBlock *BB)> IsInClonedRegion) {
   MemoryAccess *InsnDefining = MA;
   if (MemoryDef *DefMUD = dyn_cast<MemoryDef>(InsnDefining)) {
-    if (!MSSA->isLiveOnEntryDef(DefMUD)) {
-      Instruction *DefMUDI = DefMUD->getMemoryInst();
-      assert(DefMUDI && "Found MemoryUseOrDef with no Instruction.");
-      if (Instruction *NewDefMUDI =
-              cast_or_null<Instruction>(VMap.lookup(DefMUDI))) {
-        InsnDefining = MSSA->getMemoryAccess(NewDefMUDI);
-        if (!InsnDefining || isa<MemoryUse>(InsnDefining)) {
-          // The clone was simplified, it's no longer a MemoryDef, look up.
-          InsnDefining = getNewDefiningAccessForClone(
-              DefMUD->getDefiningAccess(), VMap, MPhiMap, MSSA);
-        }
-      }
+    if (MSSA->isLiveOnEntryDef(DefMUD))
+      return DefMUD;
+
+    // If the MemoryDef is not part of the cloned region, leave it alone.
+    Instruction *DefMUDI = DefMUD->getMemoryInst();
+    assert(DefMUDI && "Found MemoryUseOrDef with no Instruction.");
+    if (!IsInClonedRegion(DefMUDI->getParent()))
+      return DefMUD;
+
+    auto *NewDefMUDI = cast_or_null<Instruction>(VMap.lookup(DefMUDI));
+    InsnDefining = NewDefMUDI ? MSSA->getMemoryAccess(NewDefMUDI) : nullptr;
+    if (!InsnDefining || isa<MemoryUse>(InsnDefining)) {
+      // The clone was simplified, it's no longer a MemoryDef, look up.
+      InsnDefining = getNewDefiningAccessForClone(
+          DefMUD->getDefiningAccess(), VMap, MPhiMap, MSSA, IsInClonedRegion);
     }
   } else {
     MemoryPhi *DefPhi = cast<MemoryPhi>(InsnDefining);
@@ -593,10 +595,10 @@ static MemoryAccess *getNewDefiningAccessForClone(MemoryAccess *MA,
   return InsnDefining;
 }

-void MemorySSAUpdater::cloneUsesAndDefs(BasicBlock *BB, BasicBlock *NewBB,
-                                        const ValueToValueMapTy &VMap,
-                                        PhiToDefMap &MPhiMap,
-                                        bool CloneWasSimplified) {
+void MemorySSAUpdater::cloneUsesAndDefs(
+    BasicBlock *BB, BasicBlock *NewBB, const ValueToValueMapTy &VMap,
+    PhiToDefMap &MPhiMap, function_ref<bool(BasicBlock *)> IsInClonedRegion,
+    bool CloneWasSimplified) {
   const MemorySSA::AccessList *Acc = MSSA->getBlockAccesses(BB);
   if (!Acc)
     return;
@@ -615,7 +617,7 @@ void MemorySSAUpdater::cloneUsesAndDefs(BasicBlock *BB, BasicBlock *NewBB,
         MemoryAccess *NewUseOrDef = MSSA->createDefinedAccess(
             NewInsn,
             getNewDefiningAccessForClone(MUD->getDefiningAccess(), VMap,
-                                         MPhiMap, MSSA),
+                                         MPhiMap, MSSA, IsInClonedRegion),
             /*Template=*/CloneWasSimplified ? nullptr : MUD,
             /*CreationMustSucceed=*/false);
         if (NewUseOrDef)
@@ -668,8 +670,13 @@ void MemorySSAUpdater::updateForClonedLoop(const LoopBlocksRPO &LoopBlocks,
                                            ArrayRef<BasicBlock *> ExitBlocks,
                                            const ValueToValueMapTy &VMap,
                                            bool IgnoreIncomingWithNoClones) {
-  PhiToDefMap MPhiMap;
+  SmallSetVector<BasicBlock *, 16> Blocks;
+  for (BasicBlock *BB : concat<BasicBlock *const>(LoopBlocks, ExitBlocks))
+    Blocks.insert(BB);

+  auto IsInClonedRegion = [&](BasicBlock *BB) { return Blocks.contains(BB); };
+
+  PhiToDefMap MPhiMap;
   auto FixPhiIncomingValues = [&](MemoryPhi *Phi, MemoryPhi *NewPhi) {
     assert(Phi && NewPhi && "Invalid Phi nodes.");
     BasicBlock *NewPhiBB = NewPhi->getBlock();
@@ -692,9 +699,10 @@ void MemorySSAUpdater::updateForClonedLoop(const LoopBlocksRPO &LoopBlocks,
         continue;

       // Determine incoming value and add it as incoming from IncBB.
-      NewPhi->addIncoming(
-          getNewDefiningAccessForClone(IncomingAccess, VMap, MPhiMap, MSSA),
-          IncBB);
+      NewPhi->addIncoming(getNewDefiningAccessForClone(IncomingAccess, VMap,
+                                                       MPhiMap, MSSA,
+                                                       IsInClonedRegion),
+                          IncBB);
     }
     if (auto *SingleAccess = onlySingleValue(NewPhi)) {
       MPhiMap[Phi] = SingleAccess;
@@ -716,13 +724,13 @@ void MemorySSAUpdater::updateForClonedLoop(const LoopBlocksRPO &LoopBlocks,
       MPhiMap[MPhi] = NewPhi;
     }
     // Update Uses and Defs.
-    cloneUsesAndDefs(BB, NewBlock, VMap, MPhiMap);
+    cloneUsesAndDefs(BB, NewBlock, VMap, MPhiMap, IsInClonedRegion);
   };

-  for (auto *BB : llvm::concat<BasicBlock *const>(LoopBlocks, ExitBlocks))
+  for (auto *BB : Blocks)
     ProcessBlock(BB);

-  for (auto *BB : llvm::concat<BasicBlock *const>(LoopBlocks, ExitBlocks))
+  for (auto *BB : Blocks)
     if (MemoryPhi *MPhi = MSSA->getMemoryAccess(BB))
       if (MemoryAccess *NewPhi = MPhiMap.lookup(MPhi))
         FixPhiIncomingValues(MPhi, cast<MemoryPhi>(NewPhi));
@@ -741,7 +749,9 @@ void MemorySSAUpdater::updateForClonedBlockIntoPred(
   PhiToDefMap MPhiMap;
   if (MemoryPhi *MPhi = MSSA->getMemoryAccess(BB))
     MPhiMap[MPhi] = MPhi->getIncomingValueForBlock(P1);
-  cloneUsesAndDefs(BB, P1, VM, MPhiMap, /*CloneWasSimplified=*/true);
+  cloneUsesAndDefs(
+      BB, P1, VM, MPhiMap, [&](BasicBlock *CheckBB) { return BB == CheckBB; },
+      /*CloneWasSimplified=*/true);
 }

 template <typename Iter>

opt -disable-output -passes="loop-mssa(loop-rotate),print<memoryssa>" -verify-memoryssa < %s 2>&1

define void @test(ptr %p) {
entry:
  br label %loop

loop:
  store ptr null, ptr %p
  %val1 = load ptr, ptr %p
  %cmp = icmp eq ptr %val1, null
  br i1 %cmp, label %exit, label %loop.latch

loop.latch:
  %val2 = load ptr, ptr %p
  br label %loop

exit:
  ret void
}

opt -disable-output -passes="loop-mssa(simple-loop-unswitch<nontrivial>),print<memoryssa>" -verify-memoryssa < %s 2>&1

declare ptr @malloc() allockind("alloc,uninitialized")

define void @test(i1 %arg) {
entry:
  br label %for.body

for.body:
  %call.i = call ptr @malloc()
  %cmp.i = icmp ne ptr %call.i, null
  %or.cond.i = select i1 %cmp.i, i1 %arg, i1 false
  br i1 %or.cond.i, label %exit, label %for.body

exit:
  ret void
}

define void @test_extra_defs(ptr %p, i1 %arg) {
entry:
  store i8 1, ptr %p
  br label %for.body

for.body:
  store i8 2, ptr %p
  %call.i = call ptr @malloc()
  %cmp.i = icmp ne ptr %call.i, null
  %or.cond.i = select i1 %cmp.i, i1 %arg, i1 false
  br i1 %or.cond.i, label %exit, label %for.body

exit:
  ret void
}

[clang] Crash at -O3: Assertion `MA->use_empty() && "Trying to remove memory access that still has uses"' failed

When I compiled the code with -O3, it crashed:

Bisected to https://github.com/llvm/llvm-project/commit/5a3e3675f6be3c49fb1a305202888cce4d916ba6, which was committed by @durin42

Compiler explorer: https://godbolt.org/z/3Wc1jdx6d

```c
struct a {
  struct a *b
};
int c, g, i;
void *malloc();
int d() {
  struct a *e = malloc(c);
  if (e == 0)
    return 1;
  for (int f = 0; f < c; f++)
    e[f].b = 1 ? &e[1] : 0;
}
int h() {
  for (; g; g++)
    ;
  return 0;
}
void j() {
  for (;;)
    for (; h() + i; i++)
      d();
}
int main() {}
```
Crash is:

```
clang: /root/llvm-project/llvm/lib/Analysis/MemorySSA.cpp:1840: void llvm::MemorySSA::removeFromLookups(llvm::MemoryAccess*): Assertion `MA->use_empty() && "Trying to remove memory access that still has uses"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/clang -gdwarf-4 -g -o /app/output.s -mllvm --x86-asm-syntax=intel -fno-verbose-asm -S --gcc-toolchain=/opt/compiler-explorer/gcc-snapshot -fcolor-diagnostics -fno-crash-diagnostics -O3 -Wall -Wextra <source>
1.	<eof> parser at end of file
2.	Optimizer
3.	Running pass "require<globals-aa>,function(invalidate<aa>),require<profile-summary>,cgscc(devirt<4>(inline,function-attrs<skip-non-recursive-function-attrs>,argpromotion,openmp-opt-cgscc,function<eager-inv;no-rerun>(sroa<modify-cfg>,early-cse<memssa>,speculative-execution<only-if-divergent-target>,jump-threading,correlated-propagation,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,instcombine<max-iterations=1;no-verify-fixpoint>,aggressive-instcombine,libcalls-shrinkwrap,tailcallelim,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,reassociate,constraint-elimination,loop-mssa(loop-instsimplify,loop-simplifycfg,licm<no-allowspeculation>,loop-rotate<header-duplication;no-prepare-for-lto>,licm<allowspeculation>,simple-loop-unswitch<nontrivial;trivial>),simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,instcombine<max-iterations=1;no-verify-fixpoint>,loop(loop-idiom,indvars,simple-loop-unswitch<nontrivial;trivial>,loop-deletion,loop-unroll-full),sroa<modify-cfg>,vector-combine,mldst-motion<no-split-footer-bb>,gvn<>,sccp,bdce,instcombine<max-iterations=1;no-verify-fixpoint>,jump-threading,correlated-propagation,adce,memcpyopt,dse,move-auto-init,loop-mssa(licm<allowspeculation>),coro-elide,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,instcombine<max-iterations=1;no-verify-fixpoint>),function-attrs,function(require<should-not-run-function-passes>),coro-split,coro-annotation-elide)),function(invalidate<should-not-run-function-passes>),cgscc(devirt<4>())" on module "<source>"
4.	Running pass "cgscc(devirt<4>(inline,function-attrs<skip-non-recursive-function-attrs>,argpromotion,openmp-opt-cgscc,function<eager-inv;no-rerun>(sroa<modify-cfg>,early-cse<memssa>,speculative-execution<only-if-divergent-target>,jump-threading,correlated-propagation,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,instcombine<max-iterations=1;no-verify-fixpoint>,aggressive-instcombine,libcalls-shrinkwrap,tailcallelim,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,reassociate,constraint-elimination,loop-mssa(loop-instsimplify,loop-simplifycfg,licm<no-allowspeculation>,loop-rotate<header-duplication;no-prepare-for-lto>,licm<allowspeculation>,simple-loop-unswitch<nontrivial;trivial>),simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,instcombine<max-iterations=1;no-verify-fixpoint>,loop(loop-idiom,indvars,simple-loop-unswitch<nontrivial;trivial>,loop-deletion,loop-unroll-full),sroa<modify-cfg>,vector-combine,mldst-motion<no-split-footer-bb>,gvn<>,sccp,bdce,instcombine<max-iterations=1;no-verify-fixpoint>,jump-threading,correlated-propagation,adce,memcpyopt,dse,move-auto-init,loop-mssa(licm<allowspeculation>),coro-elide,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,instcombine<max-iterations=1;no-verify-fixpoint>),function-attrs,function(require<should-not-run-function-passes>),coro-split,coro-annotation-elide))" on module "<source>"
5.	Running pass "loop-mssa(loop-instsimplify,loop-simplifycfg,licm<no-allowspeculation>,loop-rotate<header-duplication;no-prepare-for-lto>,licm<allowspeculation>,simple-loop-unswitch<nontrivial;trivial>)" on function "j"
 #0 0x0000000003bfb838 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3bfb838)
 #1 0x0000000003bf953c llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3bf953c)
 #2 0x0000000003b46b38 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
 #3 0x00007afb46242520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #4 0x00007afb462969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #5 0x00007afb46242476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #6 0x00007afb462287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #7 0x00007afb4622871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
 #8 0x00007afb46239e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
 #9 0x0000000002bead0a llvm::MemorySSA::removeFromLookups(llvm::MemoryAccess*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x2bead0a)
#10 0x0000000002c03a6c llvm::MemorySSAUpdater::removeBlocks(llvm::SmallSetVector<llvm::BasicBlock*, 8u> const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x2c03a6c)
#11 0x00000000084e163a deleteDeadBlocksFromLoop(llvm::Loop&, llvm::SmallVectorImpl<llvm::BasicBlock*>&, llvm::DominatorTree&, llvm::LoopInfo&, llvm::MemorySSAUpdater*, llvm::ScalarEvolution*, llvm::LPMUpdater&) SimpleLoopUnswitch.cpp:0:0
#12 0x00000000084ea50d unswitchNontrivialInvariants(llvm::Loop&, llvm::Instruction&, llvm::ArrayRef<llvm::Value*>, llvm::IVConditionInfo&, llvm::DominatorTree&, llvm::LoopInfo&, llvm::AssumptionCache&, llvm::ScalarEvolution*, llvm::MemorySSAUpdater*, llvm::LPMUpdater&, bool, bool) SimpleLoopUnswitch.cpp:0:0
#13 0x00000000084ec9a8 unswitchBestCondition(llvm::Loop&, llvm::DominatorTree&, llvm::LoopInfo&, llvm::AssumptionCache&, llvm::AAResults&, llvm::TargetTransformInfo&, llvm::ScalarEvolution*, llvm::MemorySSAUpdater*, llvm::LPMUpdater&) SimpleLoopUnswitch.cpp:0:0
#14 0x00000000084f0679 llvm::SimpleLoopUnswitchPass::run(llvm::Loop&, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>&, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x84f0679)
#15 0x000000000525730e llvm::detail::PassModel<llvm::Loop, llvm::SimpleLoopUnswitchPass, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>::run(llvm::Loop&, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>&, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x525730e)
#16 0x0000000003a12986 std::optional<llvm::PreservedAnalyses> llvm::PassManager<llvm::Loop, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>::runSinglePass<llvm::Loop, std::unique_ptr<llvm::detail::PassConcept<llvm::Loop, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>, std::default_delete<llvm::detail::PassConcept<llvm::Loop, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>>>>(llvm::Loop&, std::unique_ptr<llvm::detail::PassConcept<llvm::Loop, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>, std::default_delete<llvm::detail::PassConcept<llvm::Loop, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>>>&, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>&, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&, llvm::PassInstrumentation&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3a12986)
#17 0x0000000003a12b4e llvm::PassManager<llvm::Loop, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>::runWithoutLoopNestPasses(llvm::Loop&, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>&, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3a12b4e)
#18 0x0000000003a13f04 llvm::PassManager<llvm::Loop, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>::run(llvm::Loop&, llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>&, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3a13f04)
#19 0x0000000003a14bfc llvm::FunctionToLoopPassAdaptor::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3a14bfc)
#20 0x000000000112567e llvm::detail::PassModel<llvm::Function, llvm::FunctionToLoopPassAdaptor, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x112567e)
#21 0x00000000035b06d8 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x35b06d8)
#22 0x0000000001125c2e llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x1125c2e)
#23 0x0000000002ab3c12 llvm::CGSCCToFunctionPassAdaptor::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x2ab3c12)
#24 0x000000000112607e llvm::detail::PassModel<llvm::LazyCallGraph::SCC, llvm::CGSCCToFunctionPassAdaptor, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x112607e)
#25 0x0000000002aaad52 llvm::PassManager<llvm::LazyCallGraph::SCC, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x2aaad52)
#26 0x00000000052560ce llvm::detail::PassModel<llvm::LazyCallGraph::SCC, llvm::PassManager<llvm::LazyCallGraph::SCC, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x52560ce)
#27 0x0000000002ab0666 llvm::DevirtSCCRepeatedPass::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x2ab0666)
#28 0x00000000052560ee llvm::detail::PassModel<llvm::LazyCallGraph::SCC, llvm::DevirtSCCRepeatedPass, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x52560ee)
#29 0x0000000002aae3f6 llvm::ModuleToPostOrderCGSCCPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x2aae3f6)
#30 0x00000000052560ae llvm::detail::PassModel<llvm::Module, llvm::ModuleToPostOrderCGSCCPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x52560ae)
#31 0x00000000035aeb30 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x35aeb30)
#32 0x0000000005476f75 llvm::ModuleInlinerWrapperPass::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x5476f75)
#33 0x00000000050f42ce llvm::detail::PassModel<llvm::Module, llvm::ModuleInlinerWrapperPass, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x50f42ce)
#34 0x00000000035aeb30 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x35aeb30)
#35 0x0000000003ea671b (anonymous namespace)::EmitAssemblyHelper::RunOptimizationPipeline(clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>&, std::unique_ptr<llvm::ToolOutputFile, std::default_delete<llvm::ToolOutputFile>>&, clang::BackendConsumer*) BackendUtil.cpp:0:0
#36 0x0000000003ea9f45 clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, llvm::Module*, clang::BackendAction, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>, clang::BackendConsumer*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3ea9f45)
#37 0x0000000004575cfe clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4575cfe)
#38 0x000000000673552c clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x673552c)
#39 0x00000000045760e8 clang::CodeGenAction::ExecuteAction() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x45760e8)
#40 0x00000000048312c9 clang::FrontendAction::Execute() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x48312c9)
#41 0x00000000047b04be clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x47b04be)
#42 0x000000000491c2ce clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x491c2ce)
#43 0x0000000000ceb57f cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0xceb57f)
#44 0x0000000000ce323a ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#45 0x00000000045b92e9 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::'lambda'()>(long) Job.cpp:0:0
#46 0x0000000003b46fe4 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3b46fe4)
#47 0x00000000045b98df clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (.part.0) Job.cpp:0:0
#48 0x000000000457fbcd clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x457fbcd)
#49 0x0000000004580cbd clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4580cbd)
#50 0x0000000004588075 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4588075)
#51 0x0000000000ce8419 clang_main(int, char**, llvm::ToolContext const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0xce8419)
#52 0x0000000000bb4c14 main (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0xbb4c14)
#53 0x00007afb46229d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#54 0x00007afb46229e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#55 0x0000000000ce2cee _start (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0xce2cee)
```

Reduced reproducer: https://godbolt.org/z/bK3z9nGsa
```
; bin/opt  -passes="loop-mssa(licm,simple-loop-unswitch<nontrivial;trivial>)" reduced.ll -S
; ModuleID = 'reduced.bc'
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"

; Function Attrs: allockind("alloc,uninitialized")
declare ptr @malloc() #0

define void @j(i1 %cmp2.i) {
entry:
  br label %for.cond

for.cond:                                         ; preds = %for.cond1.for.cond_crit_edge, %entry
  br label %for.cond1

for.cond1:                                        ; preds = %for.body.i, %for.body, %for.cond
  br i1 false, label %for.cond1.for.cond_crit_edge, label %for.body

for.cond1.for.cond_crit_edge:                     ; preds = %for.cond1
  br label %for.cond

for.body:                                         ; preds = %for.cond1
  %call.i = call ptr @malloc()
  %cmp.i = icmp ne ptr %call.i, null
  %or.cond.i = select i1 %cmp.i, i1 %cmp2.i, i1 false
  br i1 %or.cond.i, label %for.body.i, label %for.cond1

for.body.i:                                       ; preds = %for.body
  br label %for.cond1
}

attributes #0 = { allockind("alloc,uninitialized") }
```

Can reduce this to:

```llvm
; RUN: opt -S -passes="loop-mssa(simple-loop-unswitch<nontrivial>)" -verify-memoryssa < %s
declare ptr @malloc() allockind("alloc,uninitialized")

define void @test(i1 %arg) {
entry:
  br label %for.body

for.body:
  %call.i = call ptr @malloc()
  %cmp.i = icmp ne ptr %call.i, null
  %or.cond.i = select i1 %cmp.i, i1 %arg, i1 false
  br i1 %or.cond.i, label %exit, label %for.body

exit:
  ret void
}
```

> opt: /home/npopov/repos/llvm-project/llvm/lib/Analysis/MemorySSA.cpp:2068: void llvm::MemorySSA::verifyOrderingDominationAndDefUses(IterT, VerificationLevel) const [IterT = llvm::iterator_range<llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::BasicBlock, true, false, void, false, void>, false, false>>]: Assertion `dominates(MD, U) && "Memory Def does not dominate it's uses"' failed.

We go from:
```llvm
MemorySSA for function: test
define void @test(i1 %arg) {
entry:
  br label %for.body

for.body:                                         ; preds = %for.body, %entry
; 2 = MemoryPhi({entry,liveOnEntry},{for.body,1})
; 1 = MemoryDef(2)
  %call.i = call ptr @malloc()
  %cmp.i = icmp ne ptr %call.i, null
  %or.cond.i = select i1 %cmp.i, i1 %arg, i1 false
  br i1 %or.cond.i, label %exit, label %for.body

exit:                                             ; preds = %for.body
  ret void
}
```
To:
```llvm
MemorySSA for function: test
define void @test(i1 %arg) {
entry:
  %arg.fr = freeze i1 %arg
  br i1 %arg.fr, label %entry.split, label %entry.split.us

entry.split.us:                                   ; preds = %entry
  br label %for.body.us

for.body.us:                                      ; preds = %for.body.us, %entry.split.us
; 3 = MemoryPhi({entry.split.us,liveOnEntry},{for.body.us,1})
  br label %for.body.us

entry.split:                                      ; preds = %entry
  br label %for.body

for.body:                                         ; preds = %for.body, %entry.split
; 2 = MemoryPhi({entry.split,liveOnEntry},{for.body,1})
; 1 = MemoryDef(2)
  %call.i = call ptr @malloc()
  %cmp.i = icmp ne ptr %call.i, null
  %or.cond.i = select i1 %cmp.i, i1 true, i1 false
  br i1 %or.cond.i, label %exit, label %for.body

exit:                                             ; preds = %for.body
  ret void
}
```

MemoryPhi 3 is broken.

I think this is because we first delete the dead cloned instructions and then update MSSA and something gets confused in that case...


commit 378daa6c6fd10d3704be449f2fe9c55df522a6e9
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Thu Aug 22 17:20:47 2024 +0800

    [MemCpyOpt] Avoid infinite loops in `MemCpyOptPass::processMemCpyMemCpyDependence` (#103218)

    Closes https://github.com/llvm/llvm-project/issues/102994.

diff --git a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
index 1d779128e454..3f15fa2163d2 100644
--- a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
+++ b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
@@ -1193,6 +1193,10 @@ bool MemCpyOptPass::processMemCpyMemCpyDependence(MemCpyInst *M,
       CopySourceAlign = commonAlignment(*CopySourceAlign, MForwardOffset);
   }

+  // Avoid infinite loops
+  if (BAA.isMustAlias(M->getSource(), CopySource))
+    return false;
+
   // Verify that the copied-from memory doesn't change in between the two
   // transfers.  For example, in:
   //    memcpy(a <- b)

@g3 = external global i8, align 1

define void @func2(ptr %p) {
entry:
  %gep1 = getelementptr i8, ptr %p, i64 32
  %gep2 = getelementptr i8, ptr %p, i64 34
  %gep3 = getelementptr i8, ptr %p, i64 32
  call void @llvm.memcpy.p0.p0.i64(ptr %gep1, ptr %gep3, i64 32, i1 false)
  call void @llvm.memcpy.p0.p0.i64(ptr @g3, ptr %gep2, i64 1, i1 false)
  ret void
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) #0

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }

@g1 = external global i8
@g2 = external global [64 x i8]

define void @func() {
entry:
  call void @llvm.memcpy.p0.p0.i64(ptr getelementptr inbounds (i8, ptr @g2, i64 16), ptr getelementptr inbounds nuw (i8, ptr @g2, i64 16), i64 20, i1 false)
  call void @llvm.memcpy.p0.p0.i64(ptr @g1, ptr getelementptr inbounds (i8, ptr @g2, i64 24), i64 1, i1 false)
  ret void
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) #0

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }

[MemcpyOpt] Infinite loops when forwarding memcpy on globals

Reproducer: https://godbolt.org/z/GKzGEKE18
```
; bin/opt -passes=memcpyopt reduced.ll -S
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"

%struct.S1 = type { i64, i16, i32, %struct.S0, i8, i32, i8, i32, i8 }
%struct.S0 = type { i32, i32, i32, i32, i16 }

@g = external global i8
@g_265 = external global %struct.S1

define void @func() {
entry:
  call void @llvm.memcpy.p0.p0.i64(ptr getelementptr inbounds (i8, ptr @g_265, i64 16), ptr getelementptr inbounds nuw (i8, ptr @g_265, i64 16), i64 20, i1 false)
  call void @llvm.memcpy.p0.p0.i64(ptr @g, ptr getelementptr inbounds (i8, ptr @g_265, i64 24), i64 1, i1 false)
  ret void
}
```
```
Found roots: %entry
Clobber starting at access 1 = MemoryDef(liveOnEntry)
  for instruction   call void @llvm.memcpy.p0.p0.i64(ptr getelementptr inbounds (i8, ptr @g_265, i64 16), ptr getelementptr inbounds nuw (i8, ptr @g_265, i64 16), i64 20, i1 false)
  is 0 = MemoryDef(liveOnEntry)
Clobber starting at access 1 = MemoryDef(liveOnEntry)
  for instruction   call void @llvm.memcpy.p0.p0.i64(ptr getelementptr inbounds (i8, ptr @g_265, i64 16), ptr getelementptr inbounds nuw (i8, ptr @g_265, i64 16), i64 20, i1 false)
  is 1 = MemoryDef(liveOnEntry)
Clobber starting at access 1 = MemoryDef(liveOnEntry)
  for instruction   call void @llvm.memcpy.p0.p0.i64(ptr getelementptr inbounds (i8, ptr @g_265, i64 16), ptr getelementptr inbounds nuw (i8, ptr @g_265, i64 16), i64 20, i1 false)
  is 1 = MemoryDef(liveOnEntry)
MemCpyOptPass: Forwarding memcpy->memcpy src:
  call void @llvm.memcpy.p0.p0.i64(ptr getelementptr inbounds (i8, ptr @g_265, i64 16), ptr getelementptr inbounds nuw (i8, ptr @g_265, i64 16), i64 20, i1 false)
  call void @llvm.memcpy.p0.p0.i64(ptr @g, ptr getelementptr inbounds (i8, ptr @g_265, i64 24), i64 1, i1 false)
Clobber starting at access 1 = MemoryDef(liveOnEntry)
  for instruction   call void @llvm.memcpy.p0.p0.i64(ptr getelementptr inbounds (i8, ptr @g_265, i64 16), ptr getelementptr inbounds nuw (i8, ptr @g_265, i64 16), i64 20, i1 false)
  is 0 = MemoryDef(liveOnEntry)
Clobber starting at access 1 = MemoryDef(liveOnEntry)
  for instruction   call void @llvm.memcpy.p0.p0.i64(ptr getelementptr inbounds (i8, ptr @g_265, i64 16), ptr getelementptr inbounds nuw (i8, ptr @g_265, i64 16), i64 20, i1 false)
  is 1 = MemoryDef(liveOnEntry)
Clobber starting at access 1 = MemoryDef(liveOnEntry)
  for instruction   call void @llvm.memcpy.p0.p0.i64(ptr getelementptr inbounds (i8, ptr @g_265, i64 16), ptr getelementptr inbounds nuw (i8, ptr @g_265, i64 16), i64 20, i1 false)
  is 1 = MemoryDef(liveOnEntry)
MemCpyOptPass: Forwarding memcpy->memcpy src:
  call void @llvm.memcpy.p0.p0.i64(ptr getelementptr inbounds (i8, ptr @g_265, i64 16), ptr getelementptr inbounds nuw (i8, ptr @g_265, i64 16), i64 20, i1 false)
  call void @llvm.memcpy.p0.p0.i64(ptr @g, ptr getelementptr inbounds (i8, ptr getelementptr inbounds nuw (i8, ptr @g_265, i64 16), i64 8), i64 1, i1 false)
...
```


commit 7858e14547c509c95503b74ff8ffc7bf2fc5b110
Author: Hari Limaye <hari.limaye@arm.com>
Date:   Wed Sep 11 16:43:34 2024 +0100

    [LV] Amend check for IV increments in collectUsersInEntryBlock (#108020)

    The check for IV increments in collectUsersInEntryBlock currently
    triggers for exit-block PHIs which use the IV start value, resulting in
    us failing to add the input value for the middle block to these PHIs.

    Fix this by amending the check for IV increments to only include
    incoming values that are instructions inside the loop.

    Fixes #108004

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index b821da03c16e..640a7bf3d672 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -8663,6 +8663,7 @@ static MapVector<PHINode *, VPValue *> collectUsersInExitBlock(
          !cast<VPWidenIntOrFpInductionRecipe>(V)->getTruncInst()) ||
         isa<VPWidenPointerInductionRecipe>(V) ||
         (isa<Instruction>(IncomingValue) &&
+         OrigLoop->contains(cast<Instruction>(IncomingValue)) &&
          any_of(IncomingValue->users(), [&Inductions](User *U) {
            auto *P = dyn_cast<PHINode>(U);
            return P && Inductions.contains(P);

opt < %s -passes=loop-vectorize -force-vector-width=4 -force-vector-interleave=1 -S

define i64 @foo(ptr %p1, ptr %p2, i64 %start, i64 %end) {
entry:
  %start2 = and i64 %start, 12345
  br label %for.body

for.body:                                         ; preds = %for.body, %entry
  %ind = phi i64 [ %start2, %entry ], [ %ind.next, %for.body ]
  %arrayidx1 = getelementptr inbounds i32, ptr %p1, i64 %ind
  %0 = load i32, ptr %arrayidx1, align 4
  %arrayidx2 = getelementptr inbounds i32, ptr %p2, i64 %ind
  %1 = load i32, ptr %arrayidx2, align 4
  %ind.next = add i64 %ind, 1
  %cmp = icmp ne i64 %ind.next, %end
  br i1 %cmp, label %for.body, label %exit

exit:                                             ; preds = %for.body
  %use = phi i64 [ %start2, %for.body ]
  ret i64 %use
}

[LoopVectorize] Assertion fails when IV start value is used by an exit block PHI

With the following IR:
```
define i64 @foo(i64 %start, i64 %end) {
entry:
  %p1 = alloca [1024 x i32]
  %p2 = alloca [1024 x i32]
  call void @init_mem(ptr %p1, i64 1024)
  call void @init_mem(ptr %p2, i64 1024)
  %start2 = and i64 %start, 12345
  br label %for.body

for.body:
  %ind = phi i64 [ %ind.next, %for.body ], [ %start2, %entry ]
  %arrayidx1 = getelementptr inbounds i32, ptr %p1, i64 %ind
  %0 = load i32, ptr %arrayidx1, align 4
  %arrayidx2 = getelementptr inbounds i32, ptr %p2, i64 %ind
  %1 = load i32, ptr %arrayidx2, align 4
  %ind.next = add i64 %ind, 1
  %cmp = icmp ne i64 %ind.next, %end
  br i1 %cmp, label %for.body, label %exit

exit:
  %use =  phi i64 [ %start2, %for.body ]
  ret i64 %use
}

declare void @init_mem(ptr, i64)
```

LV crashes due to hitting the following assertion:
```
LV: Vectorizing: innermost loop.
PHINode should have one entry for each predecessor of its parent basic block!
  %bob = phi i64 [ %start2, %for.body ]
opt: /work/llvm-project-wt/nuw-clang-arr/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:10244: bool llvm::LoopVectorizePass::processLoop(Loop *): Assertion `!verif
yFunction(*L->getHeader()->getParent(), &dbgs())' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: ./build/bin/opt -passes=loop-vectorize -force-vector-interleave=2 -force-vector-width=4 -debug test.ll -o - -S
1.      Running pass "function(loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>)" on module "test.ll"
2.      Running pass "loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>" on function "foo"
 #0 0x0000aaaaaec431c0 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (./build/bin/opt+0x41a31c0)
 #1 0x0000aaaaaec4102c llvm::sys::RunSignalHandlers() (./build/bin/opt+0x41a102c)
 #2 0x0000aaaaaec438dc SignalHandler(int) Signals.cpp:0:0
 #3 0x0000fffff7ffb9d0 (linux-vdso.so.1+0x9d0)
 #4 0x0000fffff7b5f200 __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #5 0x0000fffff7b1a67c gsignal ./signal/../sysdeps/posix/raise.c:27:6
 #6 0x0000fffff7b07130 abort ./stdlib/abort.c:81:7
 #7 0x0000fffff7b13fd0 __assert_fail_base ./assert/assert.c:89:7
 #8 0x0000fffff7b14040 __assert_perror_fail ./assert/assert-perr.c:31:1
 #9 0x0000aaaaadee375c llvm::LoopVectorizePass::processLoop(llvm::Loop*) (./build/bin/opt+0x344375c)
#10 0x0000aaaaadee72d0 llvm::LoopVectorizePass::runImpl(llvm::Function&) (./build/bin/opt+0x34472d0)
#11 0x0000aaaaadee7ac0 llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (./build/bin/opt+0x3447ac0)
#12 0x0000aaaaaea9676c llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (./bui
ld/bin/opt+0x3ff676c)
#13 0x0000aaaaaea9a1fc llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (./build/bin/opt+0x3ffa1fc)
#14 0x0000aaaaaea958cc llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (./build/bin/o
pt+0x3ff58cc)
#15 0x0000aaaaab5b3d88 llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOu
tputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::ArrayRef<std::function<void (llvm::PassBuilder&)>>, llvm::opt_tool::Outpu
tKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool) (./build/bin/opt+0xb13d88)
#16 0x0000aaaaab5a7fc0 optMain (./build/bin/opt+0xb07fc0)
#17 0x0000fffff7b073fc __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:74:3
#18 0x0000fffff7b074cc call_init ./csu/../csu/libc-start.c:128:20
#19 0x0000fffff7b074cc __libc_start_main ./csu/../csu/libc-start.c:379:5
#20 0x0000aaaaab5a1ef0 _start (./build/bin/opt+0xb01ef0)
```

Seems like we fail to properly handle fixing up the incoming value for this PHI from the middle block.

Note: I am actively looking into this and plan to put up a fix


commit a3508e0246741851f06cb9ba86203be8d89febed
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Wed Oct 23 10:25:41 2024 -0700

    [SLP]Small buidlvector only graph should contains scalars from same block

    If the graph is small and has single buildvector node, all scalars
    instructions must be from the same basic block to prevent compiler
    crash.

    Fixes #113451

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 756b25ac9856..d824c40c401d 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -11588,7 +11588,8 @@ bool BoUpSLP::isTreeTinyAndNotFullyVectorizable(bool ForReduction) const {

   if (VectorizableTree.back()->isGather() &&
       VectorizableTree.back()->isAltShuffle() &&
-      VectorizableTree.back()->getVectorFactor() > 2)
+      VectorizableTree.back()->getVectorFactor() > 2 &&
+      allSameBlock(VectorizableTree.back()->Scalars))
     return false;

   assert(VectorizableTree.empty()

opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu -mattr=+avx512dq -slp-threshold=-99999 < %s

define i32 @test(i32 %arg, i32 %arg1) {
bb:
  %zext = zext i32 %arg1 to i64
  %zext2 = zext i32 %arg to i64
  %sext = sext i32 %arg to i64
  br label %bb3

bb3:                                              ; preds = %bb
  %getelementptr = getelementptr i64, ptr addrspace(1) null, i64 %zext
  %getelementptr4 = getelementptr i64, ptr addrspace(1) null, i64 %zext2
  %getelementptr5 = getelementptr i64, ptr addrspace(1) null, i64 %sext
  %zext6 = zext i32 0 to i64
  %getelementptr7 = getelementptr i64, ptr addrspace(1) null, i64 %zext6
  ret i32 0
}

To reproduce the test below with -passes slp-vectorizer -slp-threshold=-99999
```
; ModuleID = './reduced.ll'
source_filename = "./reduced.ll"
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-ni:1-p2:32:8:8:32-ni:2"
target triple = "x86_64-unknown-linux-gnu"

define i32 @wombat(i32 %arg, i32 %arg1) #0 gc "statepoint-example" {
bb:
  %zext = zext i32 %arg1 to i64
  %zext2 = zext i32 %arg to i64
  %sext = sext i32 %arg to i64
  br label %bb3

bb3:                                              ; preds = %bb
  %getelementptr = getelementptr i64, ptr addrspace(1) null, i64 %zext
  %getelementptr4 = getelementptr i64, ptr addrspace(1) null, i64 %zext2
  %getelementptr5 = getelementptr i64, ptr addrspace(1) null, i64 %sext
  %zext6 = zext i32 0 to i64
  %getelementptr7 = getelementptr i64, ptr addrspace(1) null, i64 %zext6
  ret i32 0
}

attributes #0 = { "target-features"="+prfchw,-cldemote,+avx,+aes,+sahf,+pclmul,-xop,+crc32,+xsaves,-avx512fp16,-usermsr,-sm4,-egpr,+sse4.1,-avx512ifma,+xsave,+sse4.2,-tsxldtrk,-sm3,-ptwrite,-widekl,+invpcid,+64bit,+xsavec,-avx10.1-512,-avx512vpopcntdq,+cmov,-avx512vp2intersect,+avx512cd,+movbe,-avxvnniint8,-ccmp,-amx-int8,-kl,-avx10.1-256,+evex512,-avxvnni,+rtm,+adx,+avx2,-hreset,-movdiri,-serialize,-sha512,-vpclmulqdq,+avx512vl,-uintr,-cf,+clflushopt,-raoint,-cmpccxadd,+bmi,-amx-tile,+sse,-avx10.2-256,-gfni,-avxvnniint16,-amx-fp16,-zu,-ndd,+xsaveopt,+rdrnd,+avx512f,-amx-bf16,-avx512bf16,-avx512vnni,-push2pop2,+cx8,+avx512bw,+sse3,+pku,-nf,+fsgsbase,-clzero,-mwaitx,-lwp,+lzcnt,-sha,-movdir64b,-ppx,-wbnoinvd,-enqcmd,-avx10.2-512,-avxneconvert,-tbm,-pconfig,-amx-complex,+ssse3,+cx16,+bmi2,+fma,+popcnt,-avxifma,+f16c,-avx512bitalg,-rdpru,+clwb,+mmx,+sse2,+rdseed,-avx512vbmi2,-prefetchi,-rdpid,-fma4,-avx512vbmi,-shstk,-vaes,-waitpkg,-sgx,+fxsr,+avx512dq,-sse4a,-avx512f" }

```
Reproducer: https://godbolt.org/z/8WhP4hY6G

Stack dump:
```
opt: /root/llvm-project/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp:13048: llvm::Instruction& llvm::slpvectorizer::BoUpSLP::getLastInstructionInBundle(const llvm::slpvectorizer::BoUpSLP::TreeEntry*): Assertion `((GatheredLoadsEntriesFirst.has_value() && E->getOpcode() == Instruction::Load && E->isGather() && E->Idx < *GatheredLoadsEntriesFirst) || all_of(E->Scalars, [=](Value *V) -> bool { if (E->getOpcode() == Instruction::GetElementPtr && !isa<GetElementPtrInst>(V)) return true; auto *I = cast<Instruction>(V); return !E->isOpcodeOrAlt(I) || I->getParent() == BB || isVectorLikeInstWithConstOps(I); })) && "Expected gathered loads or GEPs or instructions from same basic " "block."' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/opt -o /app/output.s -S -passes slp-vectorizer -slp-threshold=-99999 <source>
1.	Running pass "function(slp-vectorizer)" on module "<source>"
2.	Running pass "slp-vectorizer" on function "wombat"
 #0 0x00000000050d8608 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x50d8608)
 #1 0x00000000050d5fbc SignalHandler(int) Signals.cpp:0:0
 #2 0x000070a067c42520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x000070a067c969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x000070a067c42476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x000070a067c287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x000070a067c2871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
 #7 0x000070a067c39e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
 #8 0x0000000004157831 llvm::slpvectorizer::BoUpSLP::getLastInstructionInBundle(llvm::slpvectorizer::BoUpSLP::TreeEntry const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4157831)
 #9 0x0000000004157890 llvm::slpvectorizer::BoUpSLP::setInsertPointAfterBundle(llvm::slpvectorizer::BoUpSLP::TreeEntry const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4157890)
#10 0x00000000041820da llvm::slpvectorizer::BoUpSLP::vectorizeTree(llvm::slpvectorizer::BoUpSLP::TreeEntry*, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x41820da)
#11 0x00000000041a7a5c llvm::slpvectorizer::BoUpSLP::vectorizeTree(llvm::SmallDenseSet<llvm::Value*, 4u, llvm::DenseMapInfo<llvm::Value*, void>> const&, llvm::Instruction*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x41a7a5c)
#12 0x00000000041ab4ad llvm::slpvectorizer::BoUpSLP::vectorizeTree() (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x41ab4ad)
#13 0x00000000041c0e45 llvm::SLPVectorizerPass::tryToVectorizeList(llvm::ArrayRef<llvm::Value*>, llvm::slpvectorizer::BoUpSLP&, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x41c0e45)
#14 0x00000000041c2f7b llvm::SLPVectorizerPass::vectorizeGEPIndices(llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x41c2f7b)
#15 0x00000000041cf257 llvm::SLPVectorizerPass::runImpl(llvm::Function&, llvm::ScalarEvolution*, llvm::TargetTransformInfo*, llvm::TargetLibraryInfo*, llvm::AAResults*, llvm::LoopInfo*, llvm::DominatorTree*, llvm::AssumptionCache*, llvm::DemandedBits*, llvm::OptimizationRemarkEmitter*) (.part.0) SLPVectorizer.cpp:0:0
#16 0x00000000041cfedb llvm::SLPVectorizerPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x41cfedb)
#17 0x0000000002f64f0e llvm::detail::PassModel<llvm::Function, llvm::SLPVectorizerPass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x2f64f0e)
#18 0x0000000004ed9788 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4ed9788)
#19 0x0000000000e2773e llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xe2773e)
#20 0x0000000004ed81ae llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4ed81ae)
#21 0x0000000000e26e8e llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xe26e8e)
#22 0x0000000004ed7be0 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4ed7be0)
#23 0x000000000090a07a 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) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x90a07a)
#24 0x00000000008fce7c optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8fce7c)
#25 0x000070a067c29d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#26 0x000070a067c29e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#27 0x00000000008f493e _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8f493e)
Program terminated with signal: SIGSEGV
Compiler returned: 139
```


commit 79682c4d57620e623fb30271cc8003d0c9e14a01
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Tue Nov 19 11:03:11 2024 -0800

    [SLP]Check if the buildvector root is not a part of the graph before deletion

    If the buildvector root has no uses, it might be still needed as a part
    of the graph, so need to check that it is not a part of the graph before
    deletion.

    Fixes #116852

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index dc0dffd9fcbf..e70627b6afc1 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -13614,7 +13614,10 @@ Value *BoUpSLP::gather(
     } else {
       Vec = CreateShuffle(Root, Vec, Mask);
       if (auto *OI = dyn_cast<Instruction>(OriginalRoot);
-          OI && OI->hasNUses(0))
+          OI && OI->hasNUses(0) &&
+          none_of(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
+            return TE->VectorizedValue == OI;
+          }))
         eraseInstruction(OI);
     }
   }

opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu < %s

define void @test() {
;
bb:
  br label %bb1

bb1:
  %phi = phi i32 [ 0, %bb ], [ %or21, %bb1 ]
  %sitofp = sitofp i32 0 to float
  %fadd = fadd float %sitofp, %sitofp
  %fadd2 = fadd float %fadd, 0.000000e+00
  %fcmp = fcmp ogt float %fadd2, 0.000000e+00
  %select = select i1 %fcmp, i32 0, i32 0
  %select3 = select i1 false, i32 %select, i32 0
  %fadd4 = fadd float %sitofp, 0.000000e+00
  %fadd5 = fadd float %fadd4, 0.000000e+00
  %fcmp6 = fcmp ogt float %fadd5, 0.000000e+00
  %select7 = select i1 %fcmp6, i32 0, i32 0
  %select8 = select i1 false, i32 %select7, i32 0
  %or = or i32 %select3, %select8
  %sitofp9 = sitofp i32 0 to float
  %fmul = fmul float 0.000000e+00, 0.000000e+00
  %fadd10 = fadd float %sitofp9, %fmul
  %fadd11 = fadd float %fadd10, 0.000000e+00
  %fcmp12 = fcmp ogt float %fadd11, 0.000000e+00
  %select13 = select i1 %fcmp12, i32 0, i32 0
  %select14 = select i1 false, i32 %select13, i32 0
  %or15 = or i32 %select14, %or
  %fadd16 = fadd float %fmul, 0.000000e+00
  %fadd17 = fadd float %fadd16, 0.000000e+00
  %fcmp18 = fcmp ogt float %fadd17, 0.000000e+00
  %select19 = select i1 %fcmp18, i32 0, i32 0
  %select20 = select i1 false, i32 %select19, i32 0
  %or21 = or i32 %or15, %select20
  br label %bb1
}

Assertion `I->use_empty() && "trying to erase instruction with users."' failed.

To reproduce run the test below with -passes=slp-vectorizer
```
; ModuleID = './reduced.ll'
source_filename = "./reduced.ll"
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-ni:1-p2:32:8:8:32-ni:2"
target triple = "x86_64-unknown-linux-gnu"

define void @wombat() gc "statepoint-example" {
bb:
  br label %bb1

bb1:                                              ; preds = %bb1, %bb
  %phi = phi i32 [ 0, %bb ], [ %or21, %bb1 ]
  %sitofp = sitofp i32 0 to float
  %fadd = fadd float %sitofp, %sitofp
  %fadd2 = fadd float %fadd, 0.000000e+00
  %fcmp = fcmp ogt float %fadd2, 0.000000e+00
  %select = select i1 %fcmp, i32 0, i32 0
  %select3 = select i1 false, i32 %select, i32 0
  %fadd4 = fadd float %sitofp, 0.000000e+00
  %fadd5 = fadd float %fadd4, 0.000000e+00
  %fcmp6 = fcmp ogt float %fadd5, 0.000000e+00
  %select7 = select i1 %fcmp6, i32 0, i32 0
  %select8 = select i1 false, i32 %select7, i32 0
  %or = or i32 %select3, %select8
  %sitofp9 = sitofp i32 0 to float
  %fmul = fmul float 0.000000e+00, 0.000000e+00
  %fadd10 = fadd float %sitofp9, %fmul
  %fadd11 = fadd float %fadd10, 0.000000e+00
  %fcmp12 = fcmp ogt float %fadd11, 0.000000e+00
  %select13 = select i1 %fcmp12, i32 0, i32 0
  %select14 = select i1 false, i32 %select13, i32 0
  %or15 = or i32 %select14, %or
  %fadd16 = fadd float %fmul, 0.000000e+00
  %fadd17 = fadd float %fadd16, 0.000000e+00
  %fcmp18 = fcmp ogt float %fadd17, 0.000000e+00
  %select19 = select i1 %fcmp18, i32 0, i32 0
  %select20 = select i1 false, i32 %select19, i32 0
  %or21 = or i32 %or15, %select20
  br label %bb1
}
```
Reproducer: https://godbolt.org/z/T8j1xEoKM
Stack dump:
```
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/opt -o /app/output.s -S -passes=slp-vectorizer <source>
1.	Running pass "function(slp-vectorizer)" on module "<source>"
2.	Running pass "slp-vectorizer" on function "wombat"
 #0 0x0000000005194b38 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x5194b38)
 #1 0x000000000519252c SignalHandler(int) Signals.cpp:0:0
 #2 0x00007eacdf842520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x00007eacdf8969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x00007eacdf842476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x00007eacdf8287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x00007eacdf82871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
 #7 0x00007eacdf839e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
 #8 0x000000000419bb4f (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x419bb4f)
 #9 0x000000000425f0bf llvm::SLPVectorizerPass::runImpl(llvm::Function&, llvm::ScalarEvolution*, llvm::TargetTransformInfo*, llvm::TargetLibraryInfo*, llvm::AAResults*, llvm::LoopInfo*, llvm::DominatorTree*, llvm::AssumptionCache*, llvm::DemandedBits*, llvm::OptimizationRemarkEmitter*) (.part.0) SLPVectorizer.cpp:0:0
#10 0x000000000425fa7b llvm::SLPVectorizerPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x425fa7b)
#11 0x0000000002fbe41e llvm::detail::PassModel<llvm::Function, llvm::SLPVectorizerPass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x2fbe41e)
#12 0x0000000004f949e8 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4f949e8)
#13 0x0000000000e4027e llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xe4027e)
#14 0x0000000004f9340e llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4f9340e)
#15 0x0000000000e3f92e llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xe3f92e)
#16 0x0000000004f92e40 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4f92e40)
#17 0x0000000000909fda 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) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x909fda)
#18 0x00000000008fc70a optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8fc70a)
#19 0x00007eacdf829d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#20 0x00007eacdf829e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#21 0x00000000008f3e9e _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8f3e9e)
Program terminated with signal: SIGSEGV
Compiler returned: 139
```


commit 34bfed63313d1340378fc1be931253333db8c36c
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Mon Jul 15 13:00:25 2024 +0800

    [ConstantFold] Fix result type when folding powi.f16 (#98681)

    Fixes #98665.

diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 962880f68f07..6c52091cd5d7 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -2754,27 +2754,28 @@ static Constant *ConstantFoldIntrinsicCall2(Intrinsic::ID IntrinsicID, Type *Ty,
           ((Mask & fcPosInf) && Op1V.isPosInfinity());
         return ConstantInt::get(Ty, Result);
       }
+      case Intrinsic::powi: {
+        int Exp = static_cast<int>(Op2C->getSExtValue());
+        switch (Ty->getTypeID()) {
+        case Type::HalfTyID:
+        case Type::FloatTyID: {
+          APFloat Res(std::pow(Op1V.convertToFloat(), Exp));
+          if (Ty->isHalfTy()) {
+            bool Unused;
+            Res.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven,
+                        &Unused);
+          }
+          return ConstantFP::get(Ty->getContext(), Res);
+        }
+        case Type::DoubleTyID:
+          return ConstantFP::get(Ty, std::pow(Op1V.convertToDouble(), Exp));
+        default:
+          return nullptr;
+        }
+      }
       default:
         break;
       }
-
-      if (!Ty->isHalfTy() && !Ty->isFloatTy() && !Ty->isDoubleTy())
-        return nullptr;
-      if (IntrinsicID == Intrinsic::powi && Ty->isHalfTy())
-        return ConstantFP::get(
-            Ty->getContext(),
-            APFloat((float)std::pow((float)Op1V.convertToDouble(),
-                                    (int)Op2C->getZExtValue())));
-      if (IntrinsicID == Intrinsic::powi && Ty->isFloatTy())
-        return ConstantFP::get(
-            Ty->getContext(),
-            APFloat((float)std::pow((float)Op1V.convertToDouble(),
-                                    (int)Op2C->getZExtValue())));
-      if (IntrinsicID == Intrinsic::powi && Ty->isDoubleTy())
-        return ConstantFP::get(
-            Ty->getContext(),
-            APFloat((double)std::pow(Op1V.convertToDouble(),
-                                     (int)Op2C->getZExtValue())));
     }
     return nullptr;
   }

opt -passes=early-cse -earlycse-debug-hash -S -o - %s

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare double @llvm.powi.f64.i32(double, i32) #0

define double @i_powi() {
  %res = tail call fast double @llvm.powi.f64.i32(double 1.000000e+00, i32 2)
  ret double %res
}

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

define half @pr98665() {
  %x = call half @llvm.powi.f16.i32(half 0xH3C00, i32 1)
  ret half %x
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare half @llvm.powi.f16.i32(half, i32) #0

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

Misoptimization: `EarlyCSEPass` uses replaces `powi.f16` with `float` result

It looks like EarlyCSEPass is transformin the following:

```llvm
  %_6 = alloca [48 x i8], align 8
  %_3 = alloca [2 x i8], align 2
  %0 = call half @llvm.powi.f16.i32(half 0xH3C00, i32 1) ; 0xH3C00 = 1.0f16
  store half %0, ptr %_3, align 2
  %1 = load half, ptr %_3, align 2
  %_4 = fcmp oeq half %1, 0xH3C00
  br i1 %_4, label %bb1, label %bb2
```

Into this:

```llvm
  %_6 = alloca [48 x i8], align 8
  %_3 = alloca [2 x i8], align 2
  store float 1.000000e+00, ptr %_3, align 2
  %0 = load half, ptr %_3, align 2
  %_4 = fcmp oeq half %0, 0xH3C00
  br i1 %_4, label %bb1, label %bb2
```

And later InstCombine folds further into:

```llvm
  %_6 = alloca [48 x i8], align 8
  %_3 = alloca [2 x i8], align 2
  store float 1.000000e+00, ptr %_3, align 2
  br i1 false, label %bb1, label %bb2
```

EarlyCSE seems to be doing an incorrect transformation: the result of `powi.f16(1.0, 1)` should be `half` 1.0 (0x3c00), but it is returning `float` 1.0 (0x3f800000). This is incorrect and an OOB write.

This comes from the following rust code, which asserts only when optimizations are enabled:

```rust
#![feature(f16)]
#![allow(unused)]

#[inline(never)]
pub fn check_pow(a: f16) {
    assert_eq!(1.0f16.powi(1), 1.0);
}

pub fn main() {
    check_pow(1.0);
    println!("finished");
}
```

Link to compiler explorer: https://rust.godbolt.org/z/zsbzzxGvj

I'm not sure how to reduce to a llc example since the passes appear different. I have been testing on aarch64 since x86 has other f16 ABI bugs, but I don't think this is limited to aarch64.

Reproducer: https://godbolt.org/z/jhM834G3z
```
define half @test() {
    %x = call half @llvm.powi.f16.i32(half 0xH3C00, i32 1)
    ret half %x
}
```
```
opt: /root/llvm-project/llvm/lib/IR/Value.cpp:507: void llvm::Value::doRAUW(llvm::Value*, llvm::Value::ReplaceMetadataUses): Assertion `New->getType() == getType() && "replaceAllUses of value with new value of different type!"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/opt -o /app/output.s -S -passes=early-cse <source>
1.	Running pass "function(early-cse<>)" on module "<source>"
2.	Running pass "early-cse<>" on function "test"
 #0 0x0000000004e9b948 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4e9b948)
 #1 0x0000000004e990bc SignalHandler(int) Signals.cpp:0:0
 #2 0x000078ad4b442520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x000078ad4b4969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x000078ad4b442476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x000078ad4b4287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x000078ad4b42871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
 #7 0x000078ad4b439e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
 #8 0x0000000004cce094 llvm::Value::doRAUW(llvm::Value*, llvm::Value::ReplaceMetadataUses) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4cce094)
 #9 0x0000000003ae3b58 (anonymous namespace)::EarlyCSE::processNode(llvm::DomTreeNodeBase<llvm::BasicBlock>*) EarlyCSE.cpp:0:0
#10 0x0000000003ae5a85 (anonymous namespace)::EarlyCSE::run() EarlyCSE.cpp:0:0
#11 0x0000000003ae81f8 llvm::EarlyCSEPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x3ae81f8)
#12 0x0000000002ac11be llvm::detail::PassModel<llvm::Function, llvm::EarlyCSEPass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x2ac11be)
#13 0x0000000004c9f2d8 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4c9f2d8)
#14 0x0000000000dc9bee llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xdc9bee)
#15 0x0000000004c9dd46 llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4c9dd46)
#16 0x0000000000dca1fe llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xdca1fe)
#17 0x0000000004c9bf10 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4c9bf10)
#18 0x00000000008db1d2 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) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8db1d2)
#19 0x00000000008ce0fc optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8ce0fc)
#20 0x000078ad4b429d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#21 0x000078ad4b429e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#22 0x00000000008c556e _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8c556e)
Program terminated with signal: SIGSEGV
Compiler returned: 139
```

There is a bug in constant folding.