commit cb4efe1d078144a72306732a56afea3885650e8d
Author: Florian Hahn <flo@fhahn.com>
Date:   Thu Aug 22 21:38:06 2024 +0100

    [VPlan] Don't trigger VF assertion if VPlan has extra simplifications.

    There are cases where VPlans contain some simplifications that are very
    hard to accurately account for up-front in the legacy cost model. Those
    cases are caused by un-simplified inputs, which trigger the assert
    ensuring both the legacy and VPlan-based cost model agree on the VF.

    To avoid false positives due to missed simplifications in general, only
    trigger the assert if the chosen VPlan doesn't contain any additional
    simplifications.

    Fixes https://github.com/llvm/llvm-project/issues/104714.
    Fixes https://github.com/llvm/llvm-project/issues/105713.

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 8e9324ba718b..32e8f3312578 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -7237,6 +7237,56 @@ InstructionCost LoopVectorizationPlanner::cost(VPlan &Plan,
   return Cost;
 }

+/// Return true if the original loop \ TheLoop contains any instructions that do
+/// not have corresponding recipes in \p Plan and are not marked to be ignored
+/// in \p CostCtx. This means the VPlan contains simplification that the legacy
+/// cost-model did not account for.
+static bool
+planContainsAdditionalSimplifications(VPlan &Plan, ElementCount VF,
+                                      VPCostContext &CostCtx, Loop *TheLoop,
+                                      LoopVectorizationCostModel &CM) {
+  // First collect all instructions for the recipes in Plan.
+  auto GetInstructionForCost = [](const VPRecipeBase *R) -> Instruction * {
+    if (auto *S = dyn_cast<VPSingleDefRecipe>(R))
+      return dyn_cast_or_null<Instruction>(S->getUnderlyingValue());
+    if (auto *WidenMem = dyn_cast<VPWidenMemoryRecipe>(R))
+      return &WidenMem->getIngredient();
+    return nullptr;
+  };
+
+  DenseSet<Instruction *> SeenInstrs;
+  auto Iter = vp_depth_first_deep(Plan.getEntry());
+  for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(Iter)) {
+    for (VPRecipeBase &R : *VPBB) {
+      if (auto *IR = dyn_cast<VPInterleaveRecipe>(&R)) {
+        auto *IG = IR->getInterleaveGroup();
+        unsigned NumMembers = IG->getNumMembers();
+        for (unsigned I = 0; I != NumMembers; ++I) {
+          if (Instruction *M = IG->getMember(I))
+            SeenInstrs.insert(M);
+        }
+        continue;
+      }
+      if (Instruction *UI = GetInstructionForCost(&R))
+        SeenInstrs.insert(UI);
+    }
+  }
+
+  // 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, VF, &CostCtx, &CM](BasicBlock *BB) {
+        return any_of(*BB, [&SeenInstrs, VF, &CostCtx, &CM](Instruction &I) {
+          if (isa<PHINode>(&I))
+            return false;
+          return !SeenInstrs.contains(&I) &&
+                 !CostCtx.skipCostComputation(&I, true) &&
+                 !CM.canTruncateToMinimalBitwidth(&I, VF);
+        });
+      });
+}
+
 VectorizationFactor LoopVectorizationPlanner::computeBestVF() {
   if (VPlans.empty())
     return VectorizationFactor::Disabled();
@@ -7292,7 +7342,20 @@ VectorizationFactor LoopVectorizationPlanner::computeBestVF() {
   // cost-model and will be retired once the VPlan-based cost-model is
   // stabilized.
   VectorizationFactor LegacyVF = selectVectorizationFactor();
-  assert(BestFactor.Width == LegacyVF.Width &&
+  VPlan &BestPlan = getPlanFor(BestFactor.Width);
+
+  // Pre-compute the cost and use it to check if BestPlan contains any
+  // simplifications not accounted for in the legacy cost model. If that's the
+  // case, don't trigger the assertion, as the extra simplifications may cause a
+  // different VF to be picked by the VPlan-based cost model.
+  LLVMContext &LLVMCtx = OrigLoop->getHeader()->getContext();
+  VPCostContext CostCtx(CM.TTI, *CM.TLI, Legal->getWidestInductionType(),
+                        LLVMCtx, CM);
+  precomputeCosts(BestPlan, BestFactor.Width, CostCtx);
+  assert((BestFactor.Width == LegacyVF.Width ||
+          planContainsAdditionalSimplifications(getPlanFor(BestFactor.Width),
+                                                BestFactor.Width, CostCtx,
+                                                OrigLoop, CM)) &&
          " VPlan cost model and legacy cost model disagreed");
   assert((BestFactor.Width.isScalar() || BestFactor.ScalarCost > 0) &&
          "when vectorizing, the scalar cost must be computed.");

target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "riscv64-unknown-linux-gnu"

define void @empty_block_with_phi_2(ptr %src, i64 %N) #0 {
entry:
  br label %loop.header

loop.header:                                      ; preds = %loop.latch, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %xor1315 = phi i32 [ 1, %entry ], [ %xor, %loop.latch ]
  %xor = xor i32 0, 0
  %gep = getelementptr i16, ptr %src, i64 %iv
  %l = load i16, ptr %gep, align 2
  %c = icmp eq i16 %l, 0
  br i1 %c, label %loop.latch, label %else

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

loop.latch:                                       ; preds = %else, %loop.header
  %p = phi i16 [ %l, %loop.header ], [ 99, %else ]
  store i16 %p, ptr %gep, align 2
  %iv.next = add nsw i64 %iv, 1
  %0 = icmp eq i64 %iv.next, %N
  br i1 %0, label %exit, label %loop.header

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

attributes #0 = { "target-features"="+64bit,+v" }

target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "riscv64-unknown-linux-gnu"

define void @dead_load_in_block(ptr %dst, ptr %src, i8 %N, i64 %x) #0 {
entry:
  %N.ext = zext i8 %N to i64
  br label %loop.header

loop.header:                                      ; preds = %loop.latch, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %l.0 = load i32, ptr %src, align 4
  %c.0 = icmp eq i32 %l.0, 0
  br i1 %c.0, label %loop.latch, label %then

then:                                             ; preds = %loop.header
  %gep.src.x = getelementptr i32, ptr %src, i64 %x
  %l.dead = load i32, ptr %gep.src.x, align 4
  br label %loop.latch

loop.latch:                                       ; preds = %then, %loop.header
  %gep.dst = getelementptr i32, ptr %dst, i64 %iv
  store i32 0, ptr %gep.dst, align 4
  %iv.next = add i64 %iv, 3
  %cmp = icmp ult i64 %iv, %N.ext
  br i1 %cmp, label %loop.header, label %exit

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

attributes #0 = { "target-features"="+64bit,+v" }

target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "riscv64-unknown-linux-gnu"

define void @multiple_blocks_with_dead_insts_3(ptr %src) #0 {
entry:
  br label %loop.header

loop.header:                                      ; preds = %loop.latch, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %xor1315 = phi i16 [ 0, %entry ], [ %xor, %loop.latch ]
  %xor = xor i16 0, 0
  %gep = getelementptr i16, ptr %src, i64 %iv
  %l = load i16, ptr %gep, align 2
  %c = icmp eq i16 %l, 0
  br i1 %c, label %then, label %else

then:                                             ; preds = %loop.header
  %dead.gep.1 = getelementptr i64, ptr %src, i64 %iv
  br label %loop.latch

else:                                             ; preds = %loop.header
  %dead.gep.2 = getelementptr i64, ptr %src, i64 %iv
  br label %loop.latch

loop.latch:                                       ; preds = %else, %then
  store i16 %xor, ptr %gep, align 2
  %iv.next = add nsw i64 %iv, 3
  %ec = icmp eq i64 %iv.next, 1000
  br i1 %ec, label %exit, label %loop.header

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

attributes #0 = { "target-features"="+64bit,+v" }

target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "riscv64-unknown-linux-gnu"

define void @multiple_blocks_with_dead_insts_4(ptr %src, i64 %N) #0 {
entry:
  br label %loop.header

loop.header:                                      ; preds = %loop.latch, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %xor1315 = phi i16 [ 1, %entry ], [ %xor, %loop.latch ]
  %xor = xor i16 0, 0
  %gep = getelementptr i16, ptr %src, i64 %iv
  %l = load i16, ptr %gep, align 2
  %c = icmp eq i16 %l, 0
  br i1 %c, label %then, label %else

then:                                             ; preds = %loop.header
  br label %then.1

then.1:                                           ; preds = %then
  %dead.gep.1 = getelementptr i64, ptr %src, i64 %iv
  br label %loop.latch

else:                                             ; preds = %loop.header
  %dead.gep.2 = getelementptr i64, ptr %src, i64 %iv
  br label %loop.latch

loop.latch:                                       ; preds = %else, %then.1
  store i16 %xor, ptr %gep, align 2
  %iv.next = add nsw i64 %iv, 3
  %ec = icmp eq i64 %iv.next, %N
  br i1 %ec, label %exit, label %loop.header

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

attributes #0 = { "target-features"="+64bit,+v" }

target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "riscv64-unknown-linux-gnu"

define void @empty_block_with_phi_1(ptr %src, i64 %N) #0 {
entry:
  br label %loop.header

loop.header:                                      ; preds = %loop.latch, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %xor1315 = phi i32 [ 1, %entry ], [ %xor, %loop.latch ]
  %xor = xor i32 0, 0
  %gep = getelementptr i16, ptr %src, i64 %iv
  %l = load i16, ptr %gep, align 2
  %c = icmp eq i16 %l, 0
  br i1 %c, label %then, label %loop.latch

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

loop.latch:                                       ; preds = %then, %loop.header
  %p = phi i16 [ %l, %loop.header ], [ 99, %then ]
  store i16 %p, ptr %gep, align 2
  %iv.next = add nsw i64 %iv, 1
  %0 = icmp eq i64 %iv.next, %N
  br i1 %0, label %exit, label %loop.header

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

attributes #0 = { "target-features"="+64bit,+v" }

target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "riscv64-unknown-linux-gnu"

define void @block_with_dead_inst_2(ptr %src) #0 {
entry:
  br label %loop.header

loop.header:                                      ; preds = %loop.latch, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %xor1315 = phi i16 [ 0, %entry ], [ %xor, %loop.latch ]
  %xor = xor i16 0, 0
  %gep = getelementptr i16, ptr %src, i64 %iv
  %l = load i16, ptr %gep, align 2
  %c = icmp eq i16 %l, 0
  br i1 %c, label %loop.latch, label %else

else:                                             ; preds = %loop.header
  %dead.gep = getelementptr i64, ptr %src, i64 %iv
  br label %loop.latch

loop.latch:                                       ; preds = %else, %loop.header
  store i16 %xor, ptr %gep, align 2
  %iv.next = add nsw i64 %iv, 3
  %ec = icmp eq i64 %iv.next, 1000
  br i1 %ec, label %exit, label %loop.header

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

attributes #0 = { "target-features"="+64bit,+v" }

target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "riscv64-unknown-linux-gnu"

define void @multiple_blocks_with_dead_inst_multiple_successors_6(ptr %src, i1 %ic, i64 %N) #0 {
entry:
  br label %loop.header

loop.header:                                      ; preds = %loop.latch, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %xor1315 = phi i16 [ 1, %entry ], [ %xor, %loop.latch ]
  %xor = xor i16 0, 0
  %gep = getelementptr i16, ptr %src, i64 %iv
  %l = load i16, ptr %gep, align 2
  %c = icmp eq i16 %l, 0
  br i1 %c, label %then, label %else

then:                                             ; preds = %loop.header
  br i1 %ic, label %then.1, label %else

then.1:                                           ; preds = %then
  %dead.gep.1 = getelementptr i64, ptr %src, i64 %iv
  br label %loop.latch

else:                                             ; preds = %then, %loop.header
  br label %else.2

else.2:                                           ; preds = %else
  %dead.gep.2 = getelementptr i64, ptr %src, i64 %iv
  br label %loop.latch

loop.latch:                                       ; preds = %else.2, %then.1
  store i16 %xor, ptr %gep, align 2
  %iv.next = add nsw i64 %iv, 3
  %ec = icmp eq i64 %iv.next, %N
  br i1 %ec, label %exit, label %loop.header

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

attributes #0 = { "target-features"="+64bit,+v" }

target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "riscv64-unknown-linux-gnu"

define void @multiple_blocks_with_dead_inst_multiple_successors_5(ptr %src) #0 {
entry:
  br label %loop.header

loop.header:                                      ; preds = %loop.latch, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %xor1315 = phi i16 [ 1, %entry ], [ %xor, %loop.latch ]
  %xor = xor i16 0, 0
  %gep = getelementptr i16, ptr %src, i64 %iv
  %l = load i16, ptr %gep, align 2
  %c = icmp eq i16 %l, 0
  br i1 %c, label %then, label %else

then:                                             ; preds = %loop.header
  br label %then.1

then.1:                                           ; preds = %then
  %dead.gep.1 = getelementptr i64, ptr %src, i64 %iv
  br label %loop.latch

else:                                             ; preds = %loop.header
  br label %else.2

else.2:                                           ; preds = %else
  %dead.gep.2 = getelementptr i64, ptr %src, i64 %iv
  br label %loop.latch

loop.latch:                                       ; preds = %else.2, %then.1
  store i16 %xor, ptr %gep, align 2
  %iv.next = add nsw i64 %iv, 3
  %ec = icmp eq i64 %iv.next, 1000
  br i1 %ec, label %exit, label %loop.header

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

attributes #0 = { "target-features"="+64bit,+v" }

target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "riscv64-unknown-linux-gnu"

define void @block_with_dead_inst_1(ptr %src, i64 %N) #0 {
entry:
  br label %loop.header

loop.header:                                      ; preds = %loop.latch, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %xor1315 = phi i16 [ 1, %entry ], [ %xor, %loop.latch ]
  %xor = xor i16 0, 0
  %gep = getelementptr i16, ptr %src, i64 %iv
  %l = load i16, ptr %gep, align 2
  %c = icmp eq i16 %l, 0
  br i1 %c, label %then, label %loop.latch

then:                                             ; preds = %loop.header
  %dead.gep = getelementptr i64, ptr %src, i64 %iv
  br label %loop.latch

loop.latch:                                       ; preds = %then, %loop.header
  store i16 %xor, ptr %gep, align 2
  %iv.next = add nsw i64 %iv, 3
  %0 = icmp eq i64 %iv.next, %N
  br i1 %0, label %exit, label %loop.header

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

attributes #0 = { "target-features"="+64bit,+v" }

[VPlan] Assertion `VF.Width == BestVF && "VPlan cost model and legacy cost model disagreed"' failed.

Tested using d082f1f37d8cb7a0c6875537ba873a631b154d53

C Testcase:
```c
int a;
extern int b[];
signed char c;
int d[1];
void e() {
  for (short f = 2; f < c; f += 3) {
    a = ({ d[f - 1]; }) ? d[f] : 0;
    b[f] = 0;
  }
}
```
Command:
```
/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/clang -march=rv64gcv_zvl256b -O3 red.c -o /dev/null
```

Testcase:
```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 void @e(i8 %0, i64 %indvars.iv) #0 {
entry:
  %1 = zext i8 %0 to i64
  br label %for.body

for.cond.for.cond.cleanup_crit_edge:              ; preds = %cond.end
  ret void

for.body:                                         ; preds = %cond.end, %entry
  %indvars.iv1 = phi i64 [ 0, %entry ], [ %indvars.iv.next, %cond.end ]
  %sub = add i64 0, 0
  %arrayidx = getelementptr [1 x i32], ptr null, i64 0, i64 %sub
  %2 = load i32, ptr %arrayidx, align 4
  %tobool.not = icmp eq i32 %2, 0
  br i1 %tobool.not, label %cond.end, label %cond.true

cond.true:                                        ; preds = %for.body
  %arrayidx5 = getelementptr [1 x i32], ptr null, i64 0, i64 %indvars.iv
  %3 = load i32, ptr %arrayidx5, align 4
  br label %cond.end

cond.end:                                         ; preds = %cond.true, %for.body
  %arrayidx7 = getelementptr [0 x i32], ptr null, i64 0, i64 %indvars.iv1
  store i32 0, ptr %arrayidx7, align 4
  %indvars.iv.next = add i64 %indvars.iv1, 3
  %cmp = icmp ult i64 %indvars.iv1, %1
  br i1 %cmp, label %for.body, label %for.cond.for.cond.cleanup_crit_edge
}

attributes #0 = { "target-features"="+64bit,+a,+c,+d,+f,+m,+relax,+v,+zicsr,+zifencei,+zmmul,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl256b,+zvl32b,+zvl64b,-b,-e,-experimental-smmpm,-experimental-smnpm,-experimental-ssnpm,-experimental-sspm,-experimental-ssqosid,-experimental-supm,-experimental-zacas,-experimental-zalasr,-experimental-zicfilp,-experimental-zicfiss,-h,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smcdeleg,-smcsrind,-smepmp,-smstateen,-ssaia,-ssccfg,-ssccptr,-sscofpmf,-sscounterenw,-sscsrind,-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,-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:10037: bool llvm::LoopVectorizePass::processLoop(llvm::Loop*): Assertion `VF.Width == BestVF && "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 "e"
 #0 0x000063e889a673c0 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2ff63c0)
 #1 0x000063e889a647df llvm::sys::RunSignalHandlers() (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2ff37df)
 #2 0x000063e889a64935 SignalHandler(int) Signals.cpp:0:0
 #3 0x00007a5322242520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #4 0x00007a53222969fc __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #5 0x00007a53222969fc __pthread_kill_internal ./nptl/pthread_kill.c:78:10
 #6 0x00007a53222969fc pthread_kill ./nptl/pthread_kill.c:89:10
 #7 0x00007a5322242476 gsignal ./signal/../sysdeps/posix/raise.c:27:6
 #8 0x00007a53222287f3 abort ./stdlib/abort.c:81:7
 #9 0x00007a532222871b _nl_load_domain ./intl/loadmsgcat.c:1177:9
#10 0x00007a5322239e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
#11 0x000063e888a5ba9a llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x1feaa9a)
#12 0x000063e888a5df51 llvm::LoopVectorizePass::runImpl(llvm::Function&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x1fecf51)
#13 0x000063e888a5e5c7 llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x1fed5c7)
#14 0x000063e8878c6096 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+0xe55096)
#15 0x000063e88987deef 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+0x2e0ceef)
#16 0x000063e8878c91d6 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+0xe581d6)
#17 0x000063e88987cc6b llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2e0bc6b)
#18 0x000063e8878c54c6 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+0xe544c6)
#19 0x000063e88987accd 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+0x2e09ccd)
#20 0x000063e8870f3eb6 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+0x682eb6)
#21 0x000063e8870e5c41 optMain (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x674c41)
#22 0x00007a5322229d90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#23 0x00007a5322229e40 call_init ./csu/../csu/libc-start.c:128:20
#24 0x00007a5322229e40 __libc_start_main ./csu/../csu/libc-start.c:379:5
#25 0x000063e8870dbff5 _start (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x66aff5)
zsh: IOT instruction (core dumped)  /scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt
```
Godbolt: https://godbolt.org/z/v1nbzWqMb

Found via fuzzer.

cc @fhahn

Linking some meta-discussion about the assert here: https://github.com/llvm/llvm-project/issues/100591

Some additional reproducers on x86_64-linux-gnu in case they are of help:

```
[519] % clangtk -v
clang version 20.0.0git (https://github.com/llvm/llvm-project.git 410f751144e8b2e9574f03e0d0fb8560fe3cb797)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /local/suz-local/software/local/clang-trunk/bin
Build config: +assertions
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/10
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/11
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/11
Candidate multilib: .;@m64
Selected multilib: .;@m64
[520] %
[520] % clangtk -Os small.c
clang-20: /local/suz-local/software/clangbuild/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:7288: llvm::VectorizationFactor llvm::LoopVectorizationPlanner::computeBestVF(): Assertion `BestFactor.Width == LegacyVF.Width && " 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, preprocessed source, and associated run script.
Stack dump:
0.	Program arguments: /local/suz-local/software/local/clang-trunk/bin/clang-20 -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -dumpdir a- -disable-free -clear-ast-before-backend -main-file-name small.c -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/local/suz-local/software/emitesting/bugs/WAIT/20240822-clangtk-m64-Os-Wall-Wextra-pipe-fPIC-build-182745/delta -fcoverage-compilation-dir=/local/suz-local/software/emitesting/bugs/WAIT/20240822-clangtk-m64-Os-Wall-Wextra-pipe-fPIC-build-182745/delta -resource-dir /local/suz-local/software/local/clang-trunk/lib/clang/20 -I /usr/local/include -I /local/suz-local/software/local/include -internal-isystem /local/suz-local/software/local/clang-trunk/lib/clang/20/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Os -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -vectorize-loops -vectorize-slp -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/small-e51115.o -x c small.c
1.	<eof> parser at end of file
2.	Optimizer
3.	Running pass "function<eager-inv>(float2int,lower-constant-intrinsics,loop(loop-rotate<header-duplication;no-prepare-for-lto>,loop-deletion),loop-distribute,inject-tli-mappings,loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>,infer-alignment,loop-load-elim,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,simplifycfg<bonus-inst-threshold=1;forward-switch-cond;switch-range-to-icmp;switch-to-lookup;no-keep-loops;hoist-common-insts;sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,slp-vectorizer,vector-combine,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,loop-unroll<O2>,transform-warning,sroa<preserve-cfg>,infer-alignment,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,loop-mssa(licm<allowspeculation>),alignment-from-assumptions,loop-sink,instsimplify,div-rem-pairs,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-sink-common-insts;speculate-blocks;simplify-cond-branch;speculate-unpredictables>)" on module "small.c"
4.	Running pass "loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>" on function "main"
 #0 0x00005559685ec3ef llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x42ea3ef)
 #1 0x00005559685e9934 SignalHandler(int) Signals.cpp:0:0
 #2 0x00007f0380f76420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420)
 #3 0x00007f03809ad00b raise /build/glibc-LcI20x/glibc-2.31/signal/../sysdeps/unix/sysv/linux/raise.c:51:1
 #4 0x00007f038098c859 abort /build/glibc-LcI20x/glibc-2.31/stdlib/abort.c:81:7
 #5 0x00007f038098c729 get_sysdep_segment_value /build/glibc-LcI20x/glibc-2.31/intl/loadmsgcat.c:509:8
 #6 0x00007f038098c729 _nl_load_domain /build/glibc-LcI20x/glibc-2.31/intl/loadmsgcat.c:970:34
 #7 0x00007f038099dfd6 (/lib/x86_64-linux-gnu/libc.so.6+0x33fd6)
 #8 0x0000555969ef4948 llvm::LoopVectorizationPlanner::computeBestVF() (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5bf2948)
 #9 0x0000555969f0f9ea llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5c0d9ea)
#10 0x0000555969f12691 llvm::LoopVectorizePass::runImpl(llvm::Function&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5c10691)
#11 0x0000555969f12d43 llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5c10d43)
#12 0x0000555969a9d326 llvm::detail::PassModel<llvm::Function, llvm::LoopVectorizePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x579b326)
#13 0x0000555967f872a1 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x3c852a1)
#14 0x0000555965ae2ae6 llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x17e0ae6)
#15 0x0000555967f85bed llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x3c83bed)
#16 0x0000555965ae19e6 llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x17df9e6)
#17 0x0000555967f83cf1 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x3c81cf1)
#18 0x00005559688a0c29 (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
#19 0x00005559688a3d83 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*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x45a1d83)
#20 0x0000555968f440fa clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4c420fa)
#21 0x000055596ad8938c clang::ParseAST(clang::Sema&, bool, bool) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x6a8738c)
#22 0x0000555968f44598 clang::CodeGenAction::ExecuteAction() (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4c42598)
#23 0x00005559691dec59 clang::FrontendAction::Execute() (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4edcc59)
#24 0x00005559691603be clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4e5e3be)
#25 0x00005559692cb886 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4fc9886)
#26 0x00005559656b5dd5 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x13b3dd5)
#27 0x00005559656aee7a ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#28 0x00005559656b284e clang_main(int, char**, llvm::ToolContext const&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x13b084e)
#29 0x00005559655a31bb main (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x12a11bb)
#30 0x00007f038098e083 __libc_start_main /build/glibc-LcI20x/glibc-2.31/csu/../csu/libc-start.c:342:3
#31 0x00005559656ae90e _start (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x13ac90e)
clangtk: error: unable to execute command: Aborted
clangtk: error: clang frontend command failed due to signal (use -v to see invocation)
clang version 20.0.0git (https://github.com/llvm/llvm-project.git 410f751144e8b2e9574f03e0d0fb8560fe3cb797)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /local/suz-local/software/local/clang-trunk/bin
Build config: +assertions
clangtk: note: diagnostic msg:
********************

PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clangtk: note: diagnostic msg: /tmp/small-1b0f28.c
clangtk: note: diagnostic msg: /tmp/small-1b0f28.sh
clangtk: note: diagnostic msg:

********************
[521] %
[521] % cat small.c
char a;
int b, *c = &b, d[3], e;
int main() {
  int f, g[3] = {0,0,0};
  g[e] = *c = 0;
  for (; *c < 3; (*c)++) {
    f = a ? b % a : 0;
    g[2] &= d[*c] & f;
  }
  return 0;
}
```

```
[537] % clangtk -O3 small.c
clang-20: /local/suz-local/software/clangbuild/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:7288: llvm::VectorizationFactor llvm::LoopVectorizationPlanner::computeBestVF(): Assertion `BestFactor.Width == LegacyVF.Width && " 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, preprocessed source, and associated run script.
Stack dump:
0.	Program arguments: /local/suz-local/software/local/clang-trunk/bin/clang-20 -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -dumpdir a- -disable-free -clear-ast-before-backend -main-file-name small.c -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/local/suz-local/software/emitesting/bugs/WAIT/20240814-clangtk-m64-O3-build-085604/delta -fcoverage-compilation-dir=/local/suz-local/software/emitesting/bugs/WAIT/20240814-clangtk-m64-O3-build-085604/delta -resource-dir /local/suz-local/software/local/clang-trunk/lib/clang/20 -I /usr/local/include -I /local/suz-local/software/local/include -internal-isystem /local/suz-local/software/local/clang-trunk/lib/clang/20/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -vectorize-loops -vectorize-slp -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/small-83d1cf.o -x c small.c
1.	<eof> parser at end of file
2.	Optimizer
3.	Running pass "function<eager-inv>(float2int,lower-constant-intrinsics,chr,loop(loop-rotate<header-duplication;no-prepare-for-lto>,loop-deletion),loop-distribute,inject-tli-mappings,loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>,infer-alignment,loop-load-elim,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,simplifycfg<bonus-inst-threshold=1;forward-switch-cond;switch-range-to-icmp;switch-to-lookup;no-keep-loops;hoist-common-insts;sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,slp-vectorizer,vector-combine,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,loop-unroll<O3>,transform-warning,sroa<preserve-cfg>,infer-alignment,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,loop-mssa(licm<allowspeculation>),alignment-from-assumptions,loop-sink,instsimplify,div-rem-pairs,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-sink-common-insts;speculate-blocks;simplify-cond-branch;speculate-unpredictables>)" on module "small.c"
4.	Running pass "loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>" on function "main"
 #0 0x0000558427a123ef llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x42ea3ef)
 #1 0x0000558427a0f934 SignalHandler(int) Signals.cpp:0:0
 #2 0x00007fa32f70a420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420)
 #3 0x00007fa32f14100b raise /build/glibc-LcI20x/glibc-2.31/signal/../sysdeps/unix/sysv/linux/raise.c:51:1
 #4 0x00007fa32f120859 abort /build/glibc-LcI20x/glibc-2.31/stdlib/abort.c:81:7
 #5 0x00007fa32f120729 get_sysdep_segment_value /build/glibc-LcI20x/glibc-2.31/intl/loadmsgcat.c:509:8
 #6 0x00007fa32f120729 _nl_load_domain /build/glibc-LcI20x/glibc-2.31/intl/loadmsgcat.c:970:34
 #7 0x00007fa32f131fd6 (/lib/x86_64-linux-gnu/libc.so.6+0x33fd6)
 #8 0x000055842931a948 llvm::LoopVectorizationPlanner::computeBestVF() (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5bf2948)
 #9 0x00005584293359ea llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5c0d9ea)
#10 0x0000558429338691 llvm::LoopVectorizePass::runImpl(llvm::Function&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5c10691)
#11 0x0000558429338d43 llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5c10d43)
#12 0x0000558428ec3326 llvm::detail::PassModel<llvm::Function, llvm::LoopVectorizePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x579b326)
#13 0x00005584273ad2a1 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x3c852a1)
#14 0x0000558424f08ae6 llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x17e0ae6)
#15 0x00005584273abbed llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x3c83bed)
#16 0x0000558424f079e6 llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x17df9e6)
#17 0x00005584273a9cf1 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x3c81cf1)
#18 0x0000558427cc6c29 (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
#19 0x0000558427cc9d83 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*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x45a1d83)
#20 0x000055842836a0fa clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4c420fa)
#21 0x000055842a1af38c clang::ParseAST(clang::Sema&, bool, bool) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x6a8738c)
#22 0x000055842836a598 clang::CodeGenAction::ExecuteAction() (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4c42598)
#23 0x0000558428604c59 clang::FrontendAction::Execute() (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4edcc59)
#24 0x00005584285863be clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4e5e3be)
#25 0x00005584286f1886 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4fc9886)
#26 0x0000558424adbdd5 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x13b3dd5)
#27 0x0000558424ad4e7a ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#28 0x0000558424ad884e clang_main(int, char**, llvm::ToolContext const&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x13b084e)
#29 0x00005584249c91bb main (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x12a11bb)
#30 0x00007fa32f122083 __libc_start_main /build/glibc-LcI20x/glibc-2.31/csu/../csu/libc-start.c:342:3
#31 0x0000558424ad490e _start (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x13ac90e)
clangtk: error: unable to execute command: Aborted
clangtk: error: clang frontend command failed due to signal (use -v to see invocation)
clang version 20.0.0git (https://github.com/llvm/llvm-project.git 410f751144e8b2e9574f03e0d0fb8560fe3cb797)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /local/suz-local/software/local/clang-trunk/bin
Build config: +assertions
clangtk: note: diagnostic msg:
********************

PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clangtk: note: diagnostic msg: /tmp/small-aeee73.c
clangtk: note: diagnostic msg: /tmp/small-aeee73.sh
clangtk: note: diagnostic msg:

********************
[538] %
[538] % cat small.c
int a[1], *d, e, f[1];
static int b, c, *volatile g = &c;
void h(int i) { b = b >> 1 ^ a[b ^ i & 1]; }
void j(long i) {
  b = b >> 1 ^ b;
  b = b >> 1 ^ a[b ^ 1];
  h(i >> 1);
  h(i >> 3);
  h(i >> 2);
  h(i >> 4);
  h(i >> 5);
}
static void m() {
  int l;
  while (e) {
    c = 0;
    for (; c < 5; c++) {
      l = 0;
      for (; l < 7; l++)
        if (*d)
          j(f[c * l]);
    }
  }
}
int main() {
  if (e) {
    m();
    g;
  }
  return 0;
}
```

@zhendongsu  thanks for the report, it was the same issue as the test case @sjoerdmeijer shared at https://github.com/llvm/llvm-project/issues/100591, which was a different underlying issue to the one for this issue.

Both should be fixed now, please let me know if you find any other instances of this triggering.

Hi @fhahn, here is another related instance that still triggers:
```
[512] % clangtk -v
clang version 20.0.0git (https://github.com/llvm/llvm-project.git f22b1da8791edd557ce34c87190e329df2e1c892)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /local/suz-local/software/local/clang-trunk/bin
Build config: +assertions
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/10
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/11
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/11
Candidate multilib: .;@m64
Selected multilib: .;@m64
[513] %
[513] % clangtk -Os small.c
clang-20: /local/suz-local/software/clangbuild/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:7359: llvm::VectorizationFactor llvm::LoopVectorizationPlanner::computeBestVF(): Assertion `(BestFactor.Width == LegacyVF.Width || planContainsAdditionalSimplifications(getPlanFor(BestFactor.Width), BestFactor.Width, CostCtx, OrigLoop, CM)) && " 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, preprocessed source, and associated run script.
Stack dump:
0.	Program arguments: /local/suz-local/software/local/clang-trunk/bin/clang-20 -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -dumpdir a- -disable-free -clear-ast-before-backend -main-file-name small.c -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/local/suz-local/software/emitesting/bugs/20240825-clangtk-m64-Os-Wall-Wextra-pipe-fPIC-build-043108/delta -fcoverage-compilation-dir=/local/suz-local/software/emitesting/bugs/20240825-clangtk-m64-Os-Wall-Wextra-pipe-fPIC-build-043108/delta -resource-dir /local/suz-local/software/local/clang-trunk/lib/clang/20 -I /usr/local/include -I /local/suz-local/software/local/include -internal-isystem /local/suz-local/software/local/clang-trunk/lib/clang/20/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Os -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -vectorize-loops -vectorize-slp -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/small-d7ba19.o -x c small.c
1.	<eof> parser at end of file
2.	Optimizer
3.	Running pass "function<eager-inv>(float2int,lower-constant-intrinsics,loop(loop-rotate<header-duplication;no-prepare-for-lto>,loop-deletion),loop-distribute,inject-tli-mappings,loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>,infer-alignment,loop-load-elim,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,simplifycfg<bonus-inst-threshold=1;forward-switch-cond;switch-range-to-icmp;switch-to-lookup;no-keep-loops;hoist-common-insts;sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,slp-vectorizer,vector-combine,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,loop-unroll<O2>,transform-warning,sroa<preserve-cfg>,infer-alignment,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,loop-mssa(licm<allowspeculation>),alignment-from-assumptions,loop-sink,instsimplify,div-rem-pairs,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-sink-common-insts;speculate-blocks;simplify-cond-branch;speculate-unpredictables>)" on module "small.c"
4.	Running pass "loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>" on function "main"
 #0 0x0000564ef7a4babf llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x42ddabf)
 #1 0x0000564ef7a49004 SignalHandler(int) Signals.cpp:0:0
 #2 0x00007f89634f9420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420)
 #3 0x00007f8962f3000b raise /build/glibc-LcI20x/glibc-2.31/signal/../sysdeps/unix/sysv/linux/raise.c:51:1
 #4 0x00007f8962f0f859 abort /build/glibc-LcI20x/glibc-2.31/stdlib/abort.c:81:7
 #5 0x00007f8962f0f729 get_sysdep_segment_value /build/glibc-LcI20x/glibc-2.31/intl/loadmsgcat.c:509:8
 #6 0x00007f8962f0f729 _nl_load_domain /build/glibc-LcI20x/glibc-2.31/intl/loadmsgcat.c:970:34
 #7 0x00007f8962f20fd6 (/lib/x86_64-linux-gnu/libc.so.6+0x33fd6)
 #8 0x0000564ef9358b42 llvm::LoopVectorizationPlanner::computeBestVF() (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5beab42)
 #9 0x0000564ef937504a llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5c0704a)
#10 0x0000564ef9377c81 llvm::LoopVectorizePass::runImpl(llvm::Function&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5c09c81)
#11 0x0000564ef9378333 llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5c0a333)
#12 0x0000564ef8f026e6 llvm::detail::PassModel<llvm::Function, llvm::LoopVectorizePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x57946e6)
#13 0x0000564ef73e68d1 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x3c788d1)
#14 0x0000564ef4f4ff46 llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x17e1f46)
#15 0x0000564ef73e521d llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x3c7721d)
#16 0x0000564ef4f4ee46 llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x17e0e46)
#17 0x0000564ef73e3321 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x3c75321)
#18 0x0000564ef7d04bb1 (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
#19 0x0000564ef7d07d73 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*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4599d73)
#20 0x0000564ef83a840c clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4c3a40c)
#21 0x0000564efa1f004c clang::ParseAST(clang::Sema&, bool, bool) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x6a8204c)
#22 0x0000564ef83a8828 clang::CodeGenAction::ExecuteAction() (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4c3a828)
#23 0x0000564ef8643cb9 clang::FrontendAction::Execute() (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4ed5cb9)
#24 0x0000564ef85c543e clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4e5743e)
#25 0x0000564ef8730876 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4fc2876)
#26 0x0000564ef4b21e55 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x13b3e55)
#27 0x0000564ef4b1aefa ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#28 0x0000564ef4b1e8ce clang_main(int, char**, llvm::ToolContext const&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x13b08ce)
#29 0x0000564ef4a0f1bb main (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x12a11bb)
#30 0x00007f8962f11083 __libc_start_main /build/glibc-LcI20x/glibc-2.31/csu/../csu/libc-start.c:342:3
#31 0x0000564ef4b1a98e _start (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x13ac98e)
clangtk: error: unable to execute command: Aborted
clangtk: error: clang frontend command failed due to signal (use -v to see invocation)
clang version 20.0.0git (https://github.com/llvm/llvm-project.git f22b1da8791edd557ce34c87190e329df2e1c892)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /local/suz-local/software/local/clang-trunk/bin
Build config: +assertions
clangtk: note: diagnostic msg:
********************

PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clangtk: note: diagnostic msg: /tmp/small-6fc973.c
clangtk: note: diagnostic msg: /tmp/small-6fc973.sh
clangtk: note: diagnostic msg:

********************
[514] %
[514] % cat small.c
int a, d;
static int b = 1, c;
void e() {
  while (a)
    b--;
}
int main() {
  for (d = 0; d < 3; d++)
    if (a)
      for (c = 0; c < 2; c++)
        if (b)
          break;
  return 0;
}
```

Compiler Explorer: https://godbolt.org/z/zanjboPYo

Hi @fhahn, another reproducer that triggers at -O{s,2,3}:
```
[520] % clangtk -v
clang version 20.0.0git (https://github.com/llvm/llvm-project.git 7e6b1504c7cf6976ac8e9012c4513ffa258bd8eb)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /local/suz-local/software/local/clang-trunk/bin
Build config: +assertions
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/10
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/11
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/11
Candidate multilib: .;@m64
Selected multilib: .;@m64
[521] %
[521] % clangtk -O3 small.c
clang-20: /local/suz-local/software/clangbuild/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:7359: llvm::VectorizationFactor llvm::LoopVectorizationPlanner::computeBestVF(): Assertion `(BestFactor.Width == LegacyVF.Width || planContainsAdditionalSimplifications(getPlanFor(BestFactor.Width), BestFactor.Width, CostCtx, OrigLoop, CM)) && " 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, preprocessed source, and associated run script.
Stack dump:
0.	Program arguments: /local/suz-local/software/local/clang-trunk/bin/clang-20 -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -dumpdir a- -disable-free -clear-ast-before-backend -main-file-name small.c -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/local/suz-local/software/emitesting/bugs/20240826-clangtk-m64-Os-build-191303/delta -fcoverage-compilation-dir=/local/suz-local/software/emitesting/bugs/20240826-clangtk-m64-Os-build-191303/delta -resource-dir /local/suz-local/software/local/clang-trunk/lib/clang/20 -I /usr/local/include -I /local/suz-local/software/local/include -internal-isystem /local/suz-local/software/local/clang-trunk/lib/clang/20/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -vectorize-loops -vectorize-slp -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/small-bd6e8d.o -x c small.c
1.	<eof> parser at end of file
2.	Optimizer
3.	Running pass "function<eager-inv>(float2int,lower-constant-intrinsics,chr,loop(loop-rotate<header-duplication;no-prepare-for-lto>,loop-deletion),loop-distribute,inject-tli-mappings,loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>,infer-alignment,loop-load-elim,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,simplifycfg<bonus-inst-threshold=1;forward-switch-cond;switch-range-to-icmp;switch-to-lookup;no-keep-loops;hoist-common-insts;sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,slp-vectorizer,vector-combine,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,loop-unroll<O3>,transform-warning,sroa<preserve-cfg>,infer-alignment,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,loop-mssa(licm<allowspeculation>),alignment-from-assumptions,loop-sink,instsimplify,div-rem-pairs,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-sink-common-insts;speculate-blocks;simplify-cond-branch;speculate-unpredictables>)" on module "small.c"
4.	Running pass "loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>" on function "main"
 #0 0x0000561e24237f5f llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x42f4f5f)
 #1 0x0000561e242354a4 SignalHandler(int) Signals.cpp:0:0
 #2 0x00007f7461dc8420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420)
 #3 0x00007f74617ff00b raise /build/glibc-LcI20x/glibc-2.31/signal/../sysdeps/unix/sysv/linux/raise.c:51:1
 #4 0x00007f74617de859 abort /build/glibc-LcI20x/glibc-2.31/stdlib/abort.c:81:7
 #5 0x00007f74617de729 get_sysdep_segment_value /build/glibc-LcI20x/glibc-2.31/intl/loadmsgcat.c:509:8
 #6 0x00007f74617de729 _nl_load_domain /build/glibc-LcI20x/glibc-2.31/intl/loadmsgcat.c:970:34
 #7 0x00007f74617effd6 (/lib/x86_64-linux-gnu/libc.so.6+0x33fd6)
 #8 0x0000561e25b45232 llvm::LoopVectorizationPlanner::computeBestVF() (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5c02232)
 #9 0x0000561e25b616ca llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5c1e6ca)
#10 0x0000561e25b64301 llvm::LoopVectorizePass::runImpl(llvm::Function&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5c21301)
#11 0x0000561e25b649b3 llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5c219b3)
#12 0x0000561e256ef0a6 llvm::detail::PassModel<llvm::Function, llvm::LoopVectorizePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x57ac0a6)
#13 0x0000561e23bd2da1 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x3c8fda1)
#14 0x0000561e21724f86 llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x17e1f86)
#15 0x0000561e23bd16ed llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x3c8e6ed)
#16 0x0000561e21723e86 llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x17e0e86)
#17 0x0000561e23bcf7f1 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x3c8c7f1)
#18 0x0000561e244f0f41 (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
#19 0x0000561e244f4103 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*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x45b1103)
#20 0x0000561e24b9480c clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4c5180c)
#21 0x0000561e269dcc5c clang::ParseAST(clang::Sema&, bool, bool) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x6a99c5c)
#22 0x0000561e24b94c28 clang::CodeGenAction::ExecuteAction() (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4c51c28)
#23 0x0000561e24e30189 clang::FrontendAction::Execute() (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4eed189)
#24 0x0000561e24db162e clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4e6e62e)
#25 0x0000561e24f1cde6 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4fd9de6)
#26 0x0000561e212f6ed5 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x13b3ed5)
#27 0x0000561e212eff7a ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#28 0x0000561e212f394e clang_main(int, char**, llvm::ToolContext const&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x13b094e)
#29 0x0000561e211e41eb main (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x12a11eb)
#30 0x00007f74617e0083 __libc_start_main /build/glibc-LcI20x/glibc-2.31/csu/../csu/libc-start.c:342:3
#31 0x0000561e212efa0e _start (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x13aca0e)
clangtk: error: unable to execute command: Aborted
clangtk: error: clang frontend command failed due to signal (use -v to see invocation)
clang version 20.0.0git (https://github.com/llvm/llvm-project.git 7e6b1504c7cf6976ac8e9012c4513ffa258bd8eb)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /local/suz-local/software/local/clang-trunk/bin
Build config: +assertions
clangtk: note: diagnostic msg:
********************

PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clangtk: note: diagnostic msg: /tmp/small-796071.c
clangtk: note: diagnostic msg: /tmp/small-796071.sh
clangtk: note: diagnostic msg:

********************
[522] %
[522] % cat small.c
char a;
static char b, *c = &b, **d = &c;
int e;
unsigned f;
char g(int h) { return a << h; }
int main() {
  char ***i[2] = {&d, &d};
  int *j;
  for (; f < 3; f++) {
    j = &e;
    *j = g(**d);
  }
  return 0;
}
```

Compiler Explorer: https://godbolt.org/z/7Y5PzTx4P


commit b558ac0eef57a3737b1e27844115fa91e0b32582
Author: Nikita Popov <npopov@redhat.com>
Date:   Tue Jul 2 10:08:45 2024 +0200

    [InstCombine] Fix context for multi-use demanded bits simplification

    When simplifying a multi-use root value, the demanded bits were
    reset to full, but we also need to reset the context extract. To
    make this convenient (without requiring by-value passing of
    SimplifyQuery), move the logic that that handles constants and
    dispatches to SimplifyDemandedUseBits/SimplifyMultipleUseDemandedBits
    into SimplifyDemandedBits. The SimplifyDemandedInstructionBits
    caller starts with full demanded bits and an appropriate context
    anyway.

    The different context instruction does mean that the ephemeral
    value protection no longer triggers in some cases, as the changes
    to assume tests show.

    An alternative, which I will explore in a followup, is to always
    use SimplifyMultipleUseDemandedBits() -- the previous root special
    case is only really intended for SimplifyDemandedInstructionBits(),
    which now no longer shares this code path.

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

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index 318c455fd7ef..64fbcc80e0ed 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -545,10 +545,11 @@ public:
                                ConstantInt *&Less, ConstantInt *&Equal,
                                ConstantInt *&Greater);

-  /// Attempts to replace V with a simpler value based on the demanded
+  /// Attempts to replace I with a simpler value based on the demanded
   /// bits.
-  Value *SimplifyDemandedUseBits(Value *V, APInt DemandedMask, KnownBits &Known,
-                                 unsigned Depth, const SimplifyQuery &Q);
+  Value *SimplifyDemandedUseBits(Instruction *I, const APInt &DemandedMask,
+                                 KnownBits &Known, unsigned Depth,
+                                 const SimplifyQuery &Q);
   using InstCombiner::SimplifyDemandedBits;
   bool SimplifyDemandedBits(Instruction *I, unsigned Op,
                             const APInt &DemandedMask, KnownBits &Known,
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 6cf2e71363ab..b1d03786f321 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -91,8 +91,47 @@ bool InstCombinerImpl::SimplifyDemandedBits(Instruction *I, unsigned OpNo,
                                             KnownBits &Known, unsigned Depth,
                                             const SimplifyQuery &Q) {
   Use &U = I->getOperandUse(OpNo);
-  Value *NewVal = SimplifyDemandedUseBits(U.get(), DemandedMask, Known,
-                                          Depth, Q);
+  Value *V = U.get();
+  if (isa<Constant>(V)) {
+    llvm::computeKnownBits(V, Known, Depth, Q);
+    return false;
+  }
+
+  Known.resetAll();
+  if (DemandedMask.isZero()) {
+    // Not demanding any bits from V.
+    replaceUse(U, UndefValue::get(V->getType()));
+    return true;
+  }
+
+  if (Depth == MaxAnalysisRecursionDepth)
+    return false;
+
+  Instruction *VInst = dyn_cast<Instruction>(V);
+  if (!VInst) {
+    llvm::computeKnownBits(V, Known, Depth, Q);
+    return false;
+  }
+
+  Value *NewVal;
+  if (VInst->hasOneUse()) {
+    // If the instruction has one use, we can directly simplify it.
+    NewVal = SimplifyDemandedUseBits(VInst, DemandedMask, Known, Depth, Q);
+  } else if (Depth != 0) {
+    // If there are multiple uses of this instruction and we aren't at the root,
+    // then we can simplify VInst to some other value, but not modify the
+    // instruction.
+    NewVal =
+        SimplifyMultipleUseDemandedBits(VInst, DemandedMask, Known, Depth, Q);
+  } else {
+    // If this is the root being simplified, allow it to have multiple uses,
+    // just set the DemandedMask to all bits and reset the context instruction.
+    // This allows visitTruncInst (for example) to simplify the operand of a
+    // trunc without duplicating all the SimplifyDemandedUseBits() logic.
+    NewVal =
+        SimplifyDemandedUseBits(VInst, APInt::getAllOnes(Known.getBitWidth()),
+                                Known, Depth, Q.getWithInstruction(VInst));
+  }
   if (!NewVal) return false;
   if (Instruction* OpInst = dyn_cast<Instruction>(U))
     salvageDebugInfo(*OpInst);
@@ -124,50 +163,21 @@ bool InstCombinerImpl::SimplifyDemandedBits(Instruction *I, unsigned OpNo,
 /// operands based on the information about what bits are demanded. This returns
 /// some other non-null value if it found out that V is equal to another value
 /// in the context where the specified bits are demanded, but not for all users.
-Value *InstCombinerImpl::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
+Value *InstCombinerImpl::SimplifyDemandedUseBits(Instruction *I,
+                                                 const APInt &DemandedMask,
                                                  KnownBits &Known,
                                                  unsigned Depth,
                                                  const SimplifyQuery &Q) {
-  assert(V != nullptr && "Null pointer of Value???");
+  assert(I != nullptr && "Null pointer of Value???");
   assert(Depth <= MaxAnalysisRecursionDepth && "Limit Search Depth");
   uint32_t BitWidth = DemandedMask.getBitWidth();
-  Type *VTy = V->getType();
+  Type *VTy = I->getType();
   assert(
       (!VTy->isIntOrIntVectorTy() || VTy->getScalarSizeInBits() == BitWidth) &&
       Known.getBitWidth() == BitWidth &&
       "Value *V, DemandedMask and Known must have same BitWidth");

-  if (isa<Constant>(V)) {
-    llvm::computeKnownBits(V, Known, Depth, Q);
-    return nullptr;
-  }
-
-  Known.resetAll();
-  if (DemandedMask.isZero()) // Not demanding any bits from V.
-    return UndefValue::get(VTy);
-
-  if (Depth == MaxAnalysisRecursionDepth)
-    return nullptr;
-
-  Instruction *I = dyn_cast<Instruction>(V);
-  if (!I) {
-    llvm::computeKnownBits(V, Known, Depth, Q);
-    return nullptr;        // Only analyze instructions.
-  }
-
-  // If there are multiple uses of this value and we aren't at the root, then
-  // we can't do any simplifications of the operands, because DemandedMask
-  // only reflects the bits demanded by *one* of the users.
-  if (Depth != 0 && !I->hasOneUse())
-    return SimplifyMultipleUseDemandedBits(I, DemandedMask, Known, Depth, Q);
-
   KnownBits LHSKnown(BitWidth), RHSKnown(BitWidth);
-  // If this is the root being simplified, allow it to have multiple uses,
-  // just set the DemandedMask to all bits so that we can try to simplify the
-  // operands.  This allows visitTruncInst (for example) to simplify the
-  // operand of a trunc without duplicating all the logic below.
-  if (Depth == 0 && !V->hasOneUse())
-    DemandedMask.setAllBits();

   // Update flags after simplifying an operand based on the fact that some high
   // order bits are not demanded.
@@ -1105,13 +1115,13 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
     }

     if (!KnownBitsComputed)
-      llvm::computeKnownBits(V, Known, Depth, Q);
+      llvm::computeKnownBits(I, Known, Depth, Q);
     break;
   }
   }

-  if (V->getType()->isPointerTy()) {
-    Align Alignment = V->getPointerAlignment(DL);
+  if (I->getType()->isPointerTy()) {
+    Align Alignment = I->getPointerAlignment(DL);
     Known.Zero.setLowBits(Log2(Alignment));
   }

@@ -1119,13 +1129,14 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
   // constant. We can't directly simplify pointers as a constant because of
   // pointer provenance.
   // TODO: We could return `(inttoptr const)` for pointers.
-  if (!V->getType()->isPointerTy() && DemandedMask.isSubsetOf(Known.Zero | Known.One))
+  if (!I->getType()->isPointerTy() &&
+      DemandedMask.isSubsetOf(Known.Zero | Known.One))
     return Constant::getIntegerValue(VTy, Known.One);

   if (VerifyKnownBits) {
-    KnownBits ReferenceKnown = llvm::computeKnownBits(V, Depth, Q);
+    KnownBits ReferenceKnown = llvm::computeKnownBits(I, Depth, Q);
     if (Known != ReferenceKnown) {
-      errs() << "Mismatched known bits for " << *V << " in "
+      errs() << "Mismatched known bits for " << *I << " in "
              << I->getFunction()->getName() << "\n";
       errs() << "computeKnownBits(): " << ReferenceKnown << "\n";
       errs() << "SimplifyDemandedBits(): " << Known << "\n";

target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #0

define i32 @PR40940(<4 x i8> %x) {
  %shuf = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> <i32 1, i32 1, i32 2, i32 3>
  %t2 = bitcast <4 x i8> %shuf to i32
  %t3 = icmp ult i32 %t2, 65536
  call void @llvm.assume(i1 %t3)
  ret i32 %t2
}

attributes #0 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }

opt < %s -passes=instcombine -S --try-experimental-debuginfo-iterators

opt < %s -passes=instcombine --enable-knowledge-retention -S --try-experimental-debuginfo-iterators

target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #0

define i32 @PR40940(<4 x i8> %x) {
  %shuf = shufflevector <4 x i8> %x, <4 x i8> undef, <4 x i32> <i32 1, i32 1, i32 2, i32 3>
  %t2 = bitcast <4 x i8> %shuf to i32
  %t3 = icmp ult i32 %t2, 65536
  call void @llvm.assume(i1 %t3)
  ret i32 %t2
}

attributes #0 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }

!llvm.dbg.cu = !{}
!llvm.module.flags = !{!0, !1, !2, !3}

!0 = !{i32 2, !"Dwarf Version", i32 4}
!1 = !{i32 2, !"Debug Info Version", i32 3}
!2 = !{i32 1, !"wchar_size", i32 4}
!3 = !{i32 8, !"PIC Level", i32 2}

define i8 @simplifydemanded_context(i8 %x, i8 %y) {
  %and1 = and i8 %x, 1
  call void @dummy()
  %x.lobits = and i8 %x, 3
  %precond = icmp eq i8 %x.lobits, 0
  call void @llvm.assume(i1 %precond)
  %and2 = and i8 %and1, %y
  ret i8 %and2
}

declare void @dummy()

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #0

attributes #0 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }

define i16 @pr97330(i1 %c, ptr %p1, ptr %p2) {
entry:
  %v = load i64, ptr %p1, align 8
  %conv = trunc i64 %v to i16
  br i1 %c, label %exit, label %if

if:                                               ; preds = %entry
  %cmp = icmp ne i16 %conv, 1
  %conv2 = zext i1 %cmp to i32
  store i32 %conv2, ptr %p2, align 4
  %cmp2 = icmp eq i64 %v, 1
  call void @llvm.assume(i1 %cmp2)
  unreachable

exit:                                             ; preds = %entry
  ret i16 %conv
}

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #0

attributes #0 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }

[InstCombine] Miscompilation with llvm.assume in unreachable blocks

Reproducer: https://alive2.llvm.org/ce/z/zKvpXV
```
; bin/opt -passes=instcombine reduced.ll -S
define i16 @src(i16 %g, ptr %e, ptr %d) {
entry:
  %0 = load i64, ptr %d, align 8
  %conv = trunc i64 %0 to i16
  %tobool.not.i = icmp eq i16 %g, 0
  br i1 %tobool.not.i, label %i.exit, label %for.cond.preheader.i

for.cond.preheader.i:
  %cmp5.i = icmp ne i16 %g, %conv
  %conv6.i = zext i1 %cmp5.i to i32
  store i32 %conv6.i, ptr %e, align 4
  %cmp7.i = icmp eq i64 %0, 1
  call void @llvm.assume(i1 %cmp7.i)
  unreachable

i.exit:
  ret i16 %conv
}
```
```
define i16 @tgt(i16 %g, ptr %e, ptr %d) {
entry:
  %tobool.not.i = icmp eq i16 %g, 0
  br i1 %tobool.not.i, label %i.exit, label %for.cond.preheader.i

for.cond.preheader.i:                             ; preds = %entry
  unreachable

i.exit:                                           ; preds = %entry
  ret i16 1
}
```

llvm version: a8e1c3e1239604ac787b6a2d39b5278ddec8aa8a

cc @nikic

Reverting https://github.com/llvm/llvm-project/commit/11484cb817bcc2a6e2ef9572be982a1a5a4964ec fixes this issue.

I've applied two fixes for this. https://github.com/llvm/llvm-project/commit/86b37944a70229b07626e63bdb9a46b4bc3d1460 tries to stick closer to the current logic, while https://github.com/llvm/llvm-project/commit/05670b42f5b45710bfdba48dcb7e8c30c8c7478f is a more thorough fix on top of that.

Confirmed that the original case has been fixed. Thank you!

@nikic Fixed, thanks!


commit d2a26a7bd5fc7cc5752337b7f4f999642feb37dc
Author: Antonio Frighetto <me@antoniofrighetto.com>
Date:   Sun Feb 18 18:10:41 2024 +0100

    [InstCombine] Do not perform binop-of-shuffle when mask is poison

    A miscompilation issue has been addressed with refined checking.
    Shuffle masks operand may be turned into `poison` if this does
    not lead to observable changes. This however may not guarantee
    binop to binop-of-shuffle replacement to be sound anymore.

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

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 5f13454089e5..97ae980a7cba 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -1870,14 +1870,16 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
         Value *ShufOp = MatchShufAsOp0 ? X : Y;
         Value *OtherOp = MatchShufAsOp0 ? Y : X;
         for (User *U : OtherOp->users()) {
-          auto Shuf = m_Shuffle(m_Specific(ShufOp), m_Value(), m_ZeroMask());
+          ArrayRef<int> Mask;
+          auto Shuf = m_Shuffle(m_Specific(ShufOp), m_Value(), m_Mask(Mask));
           if (BO->isCommutative()
                   ? match(U, m_c_BinOp(Opcode, Shuf, m_Specific(OtherOp)))
                   : MatchShufAsOp0
                         ? match(U, m_BinOp(Opcode, Shuf, m_Specific(OtherOp)))
                         : match(U, m_BinOp(Opcode, m_Specific(OtherOp), Shuf)))
-            if (DT.dominates(U, I))
-              return U;
+            if (match(Mask, m_ZeroMask()) && Mask[0] != PoisonMaskElem)
+              if (DT.dominates(U, I))
+                return U;
         }
         return nullptr;
       };

target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"

declare void @use(<2 x i4>)

define i4 @common_binop_demand_via_extelt_op0_mismatch_elt1(<2 x i4> %x, <2 x i4> %y) {
  %xshuf = shufflevector <2 x i4> %x, <2 x i4> poison, <2 x i32> zeroinitializer
  %b_xshuf_y = sub <2 x i4> %xshuf, %y
  %b_xy = sub nsw <2 x i4> %x, %y
  %b_xy0 = extractelement <2 x i4> %b_xy, i32 1
  call void @use(<2 x i4> %b_xshuf_y)
  ret i4 %b_xy0
}

target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"

define <2 x i8> @common_binop_demand_via_splat_mask_poison(<2 x i8> %x, <2 x i8> %y) {
  %ysplat = shufflevector <2 x i8> %y, <2 x i8> poison, <2 x i32> <i32 0, i32 poison>
  %vv = add <2 x i8> %x, %ysplat
  %m = add <2 x i8> %x, %y
  %msplat = shufflevector <2 x i8> %m, <2 x i8> poison, <2 x i32> zeroinitializer
  %res = add <2 x i8> %vv, %msplat
  ret <2 x i8> %res
}

target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"

define <2 x i8> @common_binop_demand_via_splat_mask_poison_2(<2 x i8> %x, <2 x i8> %y) {
  %ysplat = shufflevector <2 x i8> %y, <2 x i8> poison, <2 x i32> <i32 poison, i32 0>
  %vv = add <2 x i8> %x, %ysplat
  %m = add <2 x i8> %x, %y
  %msplat = shufflevector <2 x i8> %m, <2 x i8> %y, <2 x i32> <i32 0, i32 2>
  %res = add <2 x i8> %vv, %msplat
  ret <2 x i8> %res
}

target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"

define <2 x i8> @common_binop_demand_via_splat_mask_poison_3(<2 x i8> %x, <2 x i8> %y) {
  %ysplat = shufflevector <2 x i8> %y, <2 x i8> poison, <2 x i32> <i32 poison, i32 0>
  %vv = add <2 x i8> %x, %ysplat
  %m = add <2 x i8> %x, %y
  %msplat = shufflevector <2 x i8> %m, <2 x i8> poison, <2 x i32> zeroinitializer
  %res = add <2 x i8> %vv, %msplat
  ret <2 x i8> %res
}

[InstCombine] Replacement of binop with binop-of-shuffle incorrectly adds extra poison value

The following IR is a minimal repro when run with `opt -passes=instcombine`:
```llvm
define i8 @src(<2 x i8> %x, <2 x i8> %y) {
  %xsplat = shufflevector <2 x i8> %x, <2 x i8> poison, <2 x i32> <i32 1, i32 0>
  %vv = mul <2 x i8> %xsplat, %y
  %m = mul <2 x i8> %x, %y   ;  <<<< Note that %m is later replaced with %vv in the output
  %msplat = shufflevector <2 x i8> %m, <2 x i8> poison, <2 x i32> <i32 0, i32 0>
  %res = add <2 x i8> %vv, %msplat
  %vget_lane = extractelement <2 x i8> %res, i64 1
  ret i8 %vget_lane
}
```
Which on 17.x or trunk will give:
```llvm
define i8 @src(<2 x i8> %x, <2 x i8> %y) {
  %xsplat = shufflevector <2 x i8> %x, <2 x i8> poison, <2 x i32> <i32 poison, i32 0>
  %vv = mul <2 x i8> %xsplat, %y
  %msplat = shufflevector <2 x i8> %vv, <2 x i8> poison, <2 x i32> <i32 poison, i32 0>
  %res = add <2 x i8> %vv, %msplat
  %vget_lane = extractelement <2 x i8> %res, i64 1
  ret i8 %vget_lane
}
```
However, this is not correct, because the added poisoned values end up observed in the final output. First, in InstCombine, the first element in each mask for the shuffles are first replaced with `poison` due to not being observed in the final `extractelement`. After that we run into this code  in `InstCombineSimplifyDemanded.cpp`:
https://github.com/llvm/llvm-project/blob/d8278b682386f51dfba204849c624672a3df40c7/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp#L1866-L1880

This is what replaces the `mul <2 x i8> %x, %y` with `mul <2 x i8> %xsplat, %y` (`m_ZeroMask` also matches poison). However in doing so, it introduces the extra poison from `%xsplat`, meaning that `%msplat` has both its elements poisoned, which ends up propagating to `%vget_lane`.

Here is a Godbolt link showing the test case on 16.x, 17.x, and trunk:
https://godbolt.org/z/5eeT7x4s3

And also an Alive2 example showing the bad transformation with a counter-example:
https://alive2.llvm.org/ce/z/RpBJEN

The code was first introduced in 3b090ff2bdb2828b53d6fec9c06b9d52fed09f42, which a bisect shows is when this first started repro'ing

I have verified that this still repros on latest trunk, 2de269a641e4ffbb7a44e559c4c0a91bb66df823

For priority/triage: this bug was found by a fuzzer meant to test SIMD codegen. It was not from manually written code

A slightly smaller test case:
https://alive2.llvm.org/ce/z/6AMPWC
```llvm
define <2 x i8> @src(<2 x i8> %x, <2 x i8> %y) {
  %xsplat = shufflevector <2 x i8> %x, <2 x i8> poison, <2 x i32> <i32 poison, i32 0>
  %vv = mul <2 x i8> %xsplat, %y
  %m = mul <2 x i8> %x, %y
  %msplat = shufflevector <2 x i8> %m, <2 x i8> poison, <2 x i32> <i32 poison, i32 0>
  %res = add <2 x i8> %vv, %msplat
  ret <2 x i8> %res
}
```
This doesn't extract the vector, and instead manually specifies the poisonous elements in the shuffles. As Alive notes, the output for `src(<0, 0>, <0, 0>)` goes from `<poison, 0>` to `<poison, poison>`


commit e7080fd735d02590cdce1bef97a7f64a34145b15
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Thu Oct 31 09:26:53 2024 -0700

    [SLP]Extra check if the intruction matked for removal, must be replaced in reduction ops

    If the instruction is vectorized and it is a part of the reduced values
    gather/buildvector node, it should replaced in reduced operation
    instructions before removal properly, to avoid compiler crash.

    Fixes #114371

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 268546fe99e1..593964177ad7 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -16127,11 +16127,13 @@ BoUpSLP::vectorizeTree(const ExtraValueToDebugLocsMap &ExternallyUsedValues,
       if (IE->Idx != 0 &&
           !(VectorizableTree.front()->isGather() &&
             !IE->UserTreeIndices.empty() &&
-            any_of(IE->UserTreeIndices,
-                   [&](const EdgeInfo &EI) {
-                     return EI.UserTE == VectorizableTree.front().get() &&
-                            EI.EdgeIdx == UINT_MAX;
-                   })) &&
+            (ValueToGatherNodes.lookup(I).contains(
+                 VectorizableTree.front().get()) ||
+             any_of(IE->UserTreeIndices,
+                    [&](const EdgeInfo &EI) {
+                      return EI.UserTE == VectorizableTree.front().get() &&
+                             EI.EdgeIdx == UINT_MAX;
+                    }))) &&
           !(GatheredLoadsEntriesFirst.has_value() &&
             IE->Idx >= *GatheredLoadsEntriesFirst &&
             VectorizableTree.front()->isGather() &&

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

define i32 @test(ptr %c, i16 %a, i16 %0) {
entry:
  %tobool = icmp ne i16 %a, 0
  %1 = zext i1 %tobool to i16
  %cmp3 = icmp ugt i16 %0, %1
  %2 = and i1 %tobool, %cmp3
  %tobool.1 = icmp ne i16 %a, 0
  %3 = zext i1 %tobool.1 to i16
  %cmp3.1 = icmp ugt i16 %0, %3
  %4 = and i1 %tobool.1, %cmp3.1
  %5 = select i1 %2, i1 %4, i1 false
  %tobool.2 = icmp ne i16 %a, 0
  %6 = zext i1 %tobool.2 to i16
  %cmp3.2 = icmp ugt i16 %0, %6
  %7 = and i1 %tobool.2, %cmp3.2
  %8 = select i1 %5, i1 %7, i1 false
  %tobool.3 = icmp ne i16 %a, 0
  %9 = zext i1 %tobool.3 to i16
  %cmp3.3 = icmp ugt i16 %a, %9
  %10 = icmp ult i16 %a, -2
  %11 = and i1 %10, %cmp3.3
  %12 = select i1 %8, i1 %11, i1 false
  %13 = zext i1 %12 to i32
  store i32 %13, ptr %c, align 4
  ret i32 0
}

clang crashes on valid code at -O{2,3} on x86_64-linux-gnu: Assertion `(I->use_empty() || all_of(I->uses(), [&](Use &U) { return isDeleted( cast<Instruction>(U.getUser())); })) && "trying to erase instruction with users."' failed

It appears to be a recent regression as it doesn't reproduce with 19.1.0 and earlier.

Compiler Explorer: https://godbolt.org/z/5Tca1zsE8

```
[507] % clangtk -v
clang version 20.0.0git (https://github.com/llvm/llvm-project.git fdc78120bde1426b223196bec645b6f27fc60f0e)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /local/suz-local/software/local/clang-trunk/bin
Build config: +assertions
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/10
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/11
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/11
Candidate multilib: .;@m64
Selected multilib: .;@m64
[508] %
[508] % clangtk -O2 small.c
clang-20: /local/suz-local/software/clangbuild/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, preprocessed source, and associated run script.
Stack dump:
0.	Program arguments: /local/suz-local/software/local/clang-trunk/bin/clang-20 -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -dumpdir a- -disable-free -clear-ast-before-backend -main-file-name small.c -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/local/suz-local/software/emitesting/bugs/20241031-clangtk-m64-O3-build-070121/delta -fcoverage-compilation-dir=/local/suz-local/software/emitesting/bugs/20241031-clangtk-m64-O3-build-070121/delta -resource-dir /local/suz-local/software/local/clang-trunk/lib/clang/20 -I /usr/local/include -I /local/suz-local/software/local/include -internal-isystem /local/suz-local/software/local/clang-trunk/lib/clang/20/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -vectorize-loops -vectorize-slp -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/small-2a4e26.o -x c small.c
1.	<eof> parser at end of file
2.	Optimizer
3.	Running pass "function<eager-inv>(float2int,lower-constant-intrinsics,loop(loop-rotate<header-duplication;no-prepare-for-lto>,loop-deletion),loop-distribute,inject-tli-mappings,loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>,infer-alignment,loop-load-elim,instcombine<max-iterations=1;no-verify-fixpoint>,simplifycfg<bonus-inst-threshold=1;forward-switch-cond;switch-range-to-icmp;switch-to-lookup;no-keep-loops;hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,slp-vectorizer,vector-combine,instcombine<max-iterations=1;no-verify-fixpoint>,loop-unroll<O2>,transform-warning,sroa<preserve-cfg>,infer-alignment,instcombine<max-iterations=1;no-verify-fixpoint>,loop-mssa(licm<allowspeculation>),alignment-from-assumptions,loop-sink,instsimplify,div-rem-pairs,tailcallelim,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;speculate-unpredictables>)" on module "small.c"
4.	Running pass "slp-vectorizer" on function "main"
 #0 0x000055e84bc23a6f llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4428a6f)
 #1 0x000055e84bc21274 SignalHandler(int) Signals.cpp:0:0
 #2 0x00007efe85a5c420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420)
 #3 0x00007efe8549300b raise /build/glibc-LcI20x/glibc-2.31/signal/../sysdeps/unix/sysv/linux/raise.c:51:1
 #4 0x00007efe85472859 abort /build/glibc-LcI20x/glibc-2.31/stdlib/abort.c:81:7
 #5 0x00007efe85472729 get_sysdep_segment_value /build/glibc-LcI20x/glibc-2.31/intl/loadmsgcat.c:509:8
 #6 0x00007efe85472729 _nl_load_domain /build/glibc-LcI20x/glibc-2.31/intl/loadmsgcat.c:970:34
 #7 0x00007efe85483fd6 (/lib/x86_64-linux-gnu/libc.so.6+0x33fd6)
 #8 0x000055e84d68990f void llvm::slpvectorizer::BoUpSLP::removeInstructionsAndOperands<llvm::Instruction>(llvm::ArrayRef<llvm::Instruction*>) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5e8e90f)
 #9 0x000055e84d6e6d28 llvm::slpvectorizer::BoUpSLP::vectorizeTree(llvm::SmallDenseSet<llvm::Value*, 4u, llvm::DenseMapInfo<llvm::Value*, void>> const&, llvm::Instruction*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5eebd28)
#10 0x000055e84d6f8d01 (anonymous namespace)::HorizontalReduction::tryToReduce(llvm::slpvectorizer::BoUpSLP&, llvm::DataLayout const&, llvm::TargetTransformInfo*, llvm::TargetLibraryInfo const&) SLPVectorizer.cpp:0:0
#11 0x000055e84d6fbb89 llvm::SLPVectorizerPass::vectorizeHorReduction(llvm::PHINode*, llvm::Instruction*, llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&, llvm::SmallVectorImpl<llvm::WeakTrackingVH>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5f00b89)
#12 0x000055e84d7004ab llvm::SLPVectorizerPass::vectorizeRootInstruction(llvm::PHINode*, llvm::Instruction*, llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&) (.constprop.0) SLPVectorizer.cpp:0:0
#13 0x000055e84d704d60 llvm::SLPVectorizerPass::vectorizeChainsInBlock(llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5f09d60)
#14 0x000055e84d70b5a0 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 0x000055e84d70c273 llvm::SLPVectorizerPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5f11273)
#16 0x000055e84d17e016 llvm::detail::PassModel<llvm::Function, llvm::SLPVectorizerPass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5983016)
#17 0x000055e84b5aa8b1 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x3daf8b1)
#18 0x000055e84909b826 llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x18a0826)
#19 0x000055e84b5a921d llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x3dae21d)
#20 0x000055e84909a226 llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x189f226)
#21 0x000055e84b5a8c51 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x3dadc51)
#22 0x000055e84bedd2d3 (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
#23 0x000055e84bee0aca 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*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x46e5aca)
#24 0x000055e84c5df37c clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4de437c)
#25 0x000055e84e4e0fac clang::ParseAST(clang::Sema&, bool, bool) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x6ce5fac)
#26 0x000055e84c5df798 clang::CodeGenAction::ExecuteAction() (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4de4798)
#27 0x000055e84c8a7649 clang::FrontendAction::Execute() (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x50ac649)
#28 0x000055e84c823e7e clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5028e7e)
#29 0x000055e84c993f46 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5198f46)
#30 0x000055e848c544f5 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x14594f5)
#31 0x000055e848c4c01a ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#32 0x000055e848c4ffd7 clang_main(int, char**, llvm::ToolContext const&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x1454fd7)
#33 0x000055e848b3a78b main (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x133f78b)
#34 0x00007efe85474083 __libc_start_main /build/glibc-LcI20x/glibc-2.31/csu/../csu/libc-start.c:342:3
#35 0x000055e848c4baae _start (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x1450aae)
clangtk: error: unable to execute command: Aborted
clangtk: error: clang frontend command failed due to signal (use -v to see invocation)
clang version 20.0.0git (https://github.com/llvm/llvm-project.git fdc78120bde1426b223196bec645b6f27fc60f0e)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /local/suz-local/software/local/clang-trunk/bin
Build config: +assertions
clangtk: note: diagnostic msg:
********************

PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clangtk: note: diagnostic msg: /tmp/small-8056bb.c
clangtk: note: diagnostic msg: /tmp/small-8056bb.sh
clangtk: note: diagnostic msg:

********************
[509] %
[509] % cat small.c
short a;
int b, d;
unsigned short c;
int main() {
  b = 0;
  for (; b < 5; b++) {
    a--;
    d |= (3 - (((!a) < 1) < c && a)) & c;
  }
  return 0;
}
```