commit cd08fadd03904806fa26a1f117879ddae34fbf67
Author: Florian Hahn <flo@fhahn.com>
Date:   Mon Aug 12 14:45:43 2024 +0100

    [LV] Include chains feeding inductions in cost precomputation.

    Include chain of ops feeding inductions in cost precomputation for
    inductions, not just the induction increment. In VPlan, those
    instructions will be cleaned up, as both phi and increment are generated
    by VPWidenIntOrFpInductionRecipe independently.

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

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 542d74ef0e1e..41e4b0fcd9b0 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -7080,7 +7080,16 @@ InstructionCost LoopVectorizationPlanner::cost(VPlan &Plan,
   for (const auto &[IV, IndDesc] : Legal->getInductionVars()) {
     Instruction *IVInc = cast<Instruction>(
         IV->getIncomingValueForBlock(OrigLoop->getLoopLatch()));
-    SmallVector<Instruction *> IVInsts = {IV, IVInc};
+    SmallVector<Instruction *> IVInsts = {IVInc};
+    for (unsigned I = 0; I != IVInsts.size(); I++) {
+      for (Value *Op : IVInsts[I]->operands()) {
+        auto *OpI = dyn_cast<Instruction>(Op);
+        if (Op == IV || !OpI || !OrigLoop->contains(OpI) || !Op->hasOneUse())
+          continue;
+        IVInsts.push_back(OpI);
+      }
+    }
+    IVInsts.push_back(IV);
     for (User *U : IV->users()) {
       auto *CI = cast<Instruction>(U);
       if (!CostCtx.CM.isOptimizableIVTruncate(CI, VF))

opt -p loop-vectorize -mtriple=x86_64-apple-macosx -S %s

target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"

define i16 @iv_and_step_trunc() {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %rec = phi i16 [ 0, %entry ], [ %rec.next, %loop ]
  %iv.next = add i64 %iv, 1
  %0 = trunc i64 %iv to i16
  %1 = trunc i64 %iv.next to i16
  %rec.next = mul i16 %0, %1
  %ec = icmp eq i64 %iv, 1
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop
  ret i16 %rec
}

target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"

define void @wombat2(i32 %arg, ptr %dst) #0 {
entry:
  %mul = mul i32 %arg, 3
  %zext = zext i32 %arg to i64
  br label %loop

loop:                                             ; preds = %loop, %entry
  %phi = phi i64 [ 4, %entry ], [ %add, %loop ]
  %phi2 = phi i32 [ %mul, %entry ], [ %trunc.1, %loop ]
  %getelementptr = getelementptr i32, ptr %dst, i64 %phi
  %and = and i32 %phi2, 12
  store i32 %and, ptr %getelementptr, align 4
  %mul3 = mul i64 %phi, %zext
  %add = add i64 %phi, 1
  %icmp = icmp ugt i64 %phi, 65
  %trunc.0 = trunc i64 %mul3 to i60
  %trunc.1 = trunc i60 %trunc.0 to i32
  br i1 %icmp, label %exit, label %loop

exit:                                             ; preds = %loop
  ret void
}

attributes #0 = { "target-cpu"="skylake-avx512" "target-features"="-avx512f" }

target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"

define void @with_dead_use(i32 %arg, ptr %dst) #0 {
entry:
  %mul = mul i32 %arg, 3
  %zext = zext i32 %arg to i64
  br label %loop

loop:                                             ; preds = %loop, %entry
  %phi = phi i64 [ 4, %entry ], [ %add, %loop ]
  %phi2 = phi i32 [ %mul, %entry ], [ %trunc, %loop ]
  %getelementptr = getelementptr i32, ptr %dst, i64 %phi
  %and = and i32 %phi2, 12
  store i32 %and, ptr %getelementptr, align 4
  %mul3 = mul i64 %phi, %zext
  %add = add i64 %phi, 1
  %icmp = icmp ugt i64 %phi, 65
  %trunc = trunc i64 %mul3 to i32
  %dead.and = and i32 %trunc, 123
  br i1 %icmp, label %exit, label %loop

exit:                                             ; preds = %loop
  ret void
}

attributes #0 = { "target-cpu"="skylake-avx512" "target-features"="-avx512f" }

target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"

define i32 @test_scalar_predicated_cost(i64 %x, i64 %y, ptr %A) #0 {
entry:
  br label %loop.header

loop.header:                                      ; preds = %loop.latch, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %cmp9.not = icmp ule i64 %iv, %y
  br i1 %cmp9.not, label %loop.latch, label %if.then

if.then:                                          ; preds = %loop.header
  %or = or i64 %x, %iv
  %gep = getelementptr i32, ptr %A, i64 %iv
  %t = trunc i64 %or to i32
  store i32 %t, ptr %gep, align 4
  br label %loop.latch

loop.latch:                                       ; preds = %if.then, %loop.header
  %iv.next = add i64 %iv, 1
  %ec = icmp eq i64 %iv, 100
  br i1 %ec, label %exit, label %loop.header

exit:                                             ; preds = %loop.latch
  ret i32 0
}

attributes #0 = { "min-legal-vector-width"="0" "target-cpu"="skylake-avx512" }

target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"

define void @truncated_ivs_with_wide_and_scalar_uses(i1 %c, ptr %dst) {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %iv.16 = trunc i64 %iv to i16
  %iv.32 = trunc i64 %iv to i32
  %gep = getelementptr i16, ptr %dst, i32 %iv.32
  %sel = select i1 %c, i16 %iv.16, i16 10
  store i16 %sel, ptr %gep, align 2
  %iv.next = add i64 %iv, 1
  %ec = icmp eq i64 %iv, 64
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop
  ret void
}

target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"

define void @multiple_truncated_ivs_with_wide_uses(i1 %c, ptr %A, ptr %B) {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %iv.16 = trunc i64 %iv to i16
  %iv.32 = trunc i64 %iv to i32
  %sel = select i1 %c, i16 %iv.16, i16 10
  %gep.A = getelementptr i16, ptr %A, i64 %iv
  store i16 %sel, ptr %gep.A, align 2
  %gep.B = getelementptr i32, ptr %B, i64 %iv
  store i32 %iv.32, ptr %gep.B, align 4
  %iv.next = add i64 %iv, 1
  %ec = icmp eq i64 %iv, 64
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop
  ret void
}

target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"

define void @wide_iv_trunc_reuse(ptr %dst) {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 1, %entry ], [ %iv.next, %loop ]
  %iv.2 = phi i32 [ 0, %entry ], [ %iv.trunc, %loop ]
  store i32 %iv.2, ptr %dst, align 4
  %iv.next = add i64 %iv, 1
  %ec = icmp eq i64 %iv, 0
  %iv.trunc = trunc i64 %iv to i32
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop
  ret void
}

target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"

define i32 @iv_used_widened_and_truncated(ptr %dst, i64 %N) #0 {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %gep = getelementptr { i32, [8 x i32] }, ptr %dst, i64 %iv
  %t = trunc i64 %iv to i32
  store i32 %t, ptr %gep, align 8
  %iv.next = add i64 %iv, 1
  %c = icmp eq i64 %iv, %N
  br i1 %c, label %exit, label %loop

exit:                                             ; preds = %loop
  ret i32 0
}

attributes #0 = { "min-legal-vector-width"="0" "target-cpu"="skylake-avx512" }

target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"

define void @wombat(i32 %arg, ptr %dst) #0 {
entry:
  %mul = mul i32 %arg, 3
  %zext = zext i32 %arg to i64
  br label %loop

loop:                                             ; preds = %loop, %entry
  %phi = phi i64 [ 4, %entry ], [ %add, %loop ]
  %phi2 = phi i32 [ %mul, %entry ], [ %trunc, %loop ]
  %getelementptr = getelementptr i32, ptr %dst, i64 %phi
  %and = and i32 %phi2, 12
  store i32 %and, ptr %getelementptr, align 4
  %mul3 = mul i64 %phi, %zext
  %add = add i64 %phi, 1
  %icmp = icmp ugt i64 %phi, 65
  %trunc = trunc i64 %mul3 to i32
  br i1 %icmp, label %exit, label %loop

exit:                                             ; preds = %loop
  ret void
}

attributes #0 = { "target-cpu"="skylake-avx512" "target-features"="-avx512f" }

target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"

define void @wide_iv_trunc(ptr %dst, i64 %N) {
entry:
  %cmp = icmp ult i64 %N, 8
  br i1 %cmp, label %loop, label %exit

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %iv.trunc = trunc i64 %iv to i32
  store i32 %iv.trunc, ptr %dst, align 4
  %iv.next = add i64 %iv, 1
  %ec = icmp eq i64 %iv, %N
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop, %entry
  ret void
}

target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"

define void @multiple_pointer_ivs_with_scalar_uses_only(ptr %A, ptr %B) #0 {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv.1 = phi i32 [ 100, %entry ], [ %dec, %loop ]
  %iv.2 = phi i32 [ 2048, %entry ], [ %add38, %loop ]
  %ptr.iv.1 = phi ptr [ %A, %entry ], [ %outptr.0, %loop ]
  %ptr.iv.2 = phi ptr [ %B, %entry ], [ %incdec.ptr36, %loop ]
  %ptr.iv.3 = phi ptr [ %B, %entry ], [ %incdec.ptr33, %loop ]
  %incdec.ptr33 = getelementptr i8, ptr %ptr.iv.3, i64 1
  %0 = load i8, ptr %ptr.iv.3, align 1
  %conv34 = zext i8 %0 to i32
  %incdec.ptr36 = getelementptr i8, ptr %ptr.iv.2, i64 1
  %1 = load i8, ptr %ptr.iv.2, align 1
  %conv37 = zext i8 %1 to i32
  %add38 = add i32 %conv34, %conv37
  %shr42 = lshr i32 %iv.2, 1
  %conv43 = trunc i32 %shr42 to i8
  store i8 %conv43, ptr %ptr.iv.1, align 1
  %dec = add i32 %iv.1, 1
  %outptr.0 = getelementptr i8, ptr %ptr.iv.1, i64 2
  %cmp30.not = icmp eq i32 %dec, 0
  br i1 %cmp30.not, label %exit, label %loop

exit:                                             ; preds = %loop
  ret void
}

attributes #0 = { "min-legal-vector-width"="0" "target-cpu"="skylake-avx512" }

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

To reproduce run opt with
```
-passes=loop-vectorize --mcpu=skylake-avx512 --mattr=+prfchw,-cldemote,+avx,+aes,+sahf,+pclmul,-xop,+crc32,+xsaves,-avx512fp16,-usermsr,-sm4,-egpr,+sse4.1,-avx512ifma,+xsave,+sse4.2,-tsxldtrk,-sm3,-ptwrite,-widekl,+invpcid,+64bit,+xsavec,-avx10.1-512,-avx512vpopcntdq,+cmov,-avx512vp2intersect,+avx512cd,+movbe,-avxvnniint8,-ccmp,-amx-int8,-kl,-avx10.1-256,+evex512,-avxvnni,+rtm,+adx,+avx2,-hreset,-movdiri,-serialize,-sha512,-vpclmulqdq,+avx512vl,-uintr,-cf,+clflushopt,-raoint,-cmpccxadd,+bmi,-amx-tile,+sse,-gfni,-avxvnniint16,-amx-fp16,-zu,-ndd,+xsaveopt,+rdrnd,+avx512f,-amx-bf16,-avx512bf16,-avx512vnni,-push2pop2,+cx8,+avx512bw,+sse3,+pku,-nf,+fsgsbase,-clzero,-mwaitx,-lwp,+lzcnt,-sha,-movdir64b,-ppx,-wbnoinvd,-enqcmd,-avxneconvert,-tbm,-pconfig,-amx-complex,+ssse3,+cx16,+bmi2,+fma,+popcnt,-avxifma,+f16c,-avx512bitalg,-rdpru,+clwb,+mmx,+sse2,+rdseed,-avx512vbmi2,-prefetchi,-rdpid,-fma4,-avx512vbmi,-shstk,-vaes,-waitpkg,-sgx,+fxsr,+avx512dq,-sse4a,-avx512f
```
with the following test:
```
; ModuleID = './reduced.ll'
source_filename = "./reduced.ll"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128-ni:1-p2:32:8:8:32-ni:2"
target triple = "x86_64-unknown-linux-gnu"

define void @wombat(i32 %arg) #0 gc "statepoint-example" {
bb:
  %mul = mul i32 %arg, 3
  %zext = zext i32 %arg to i64
  br label %bb1

bb1:                                              ; preds = %bb1, %bb
  %phi = phi i64 [ %add, %bb1 ], [ 4, %bb ]
  %phi2 = phi i32 [ %trunc, %bb1 ], [ %mul, %bb ]
  %getelementptr = getelementptr i32, ptr addrspace(1) null, i64 %phi
  %and = and i32 %phi2, 0
  store i32 0, ptr addrspace(1) %getelementptr, align 4
  %mul3 = mul i64 %phi, %zext
  %add = add i64 %phi, 1
  %icmp = icmp ugt i64 %phi, 65
  %trunc = trunc i64 %mul3 to i32
  br i1 %icmp, label %bb4, label %bb1

bb4:                                              ; preds = %bb1
  ret void
}
```
Reproducer:  https://godbolt.org/z/nPsP7h51n

Stack dump:
```
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/opt -o /app/output.s -S -passes=loop-vectorize --mcpu=skylake-avx512 --mattr=+prfchw,-cldemote,+avx,+aes,+sahf,+pclmul,-xop,+crc32,+xsaves,-avx512fp16,-usermsr,-sm4,-egpr,+sse4.1,-avx512ifma,+xsave,+sse4.2,-tsxldtrk,-sm3,-ptwrite,-widekl,+invpcid,+64bit,+xsavec,-avx10.1-512,-avx512vpopcntdq,+cmov,-avx512vp2intersect,+avx512cd,+movbe,-avxvnniint8,-ccmp,-amx-int8,-kl,-avx10.1-256,+evex512,-avxvnni,+rtm,+adx,+avx2,-hreset,-movdiri,-serialize,-sha512,-vpclmulqdq,+avx512vl,-uintr,-cf,+clflushopt,-raoint,-cmpccxadd,+bmi,-amx-tile,+sse,-gfni,-avxvnniint16,-amx-fp16,-zu,-ndd,+xsaveopt,+rdrnd,+avx512f,-amx-bf16,-avx512bf16,-avx512vnni,-push2pop2,+cx8,+avx512bw,+sse3,+pku,-nf,+fsgsbase,-clzero,-mwaitx,-lwp,+lzcnt,-sha,-movdir64b,-ppx,-wbnoinvd,-enqcmd,-avxneconvert,-tbm,-pconfig,-amx-complex,+ssse3,+cx16,+bmi2,+fma,+popcnt,-avxifma,+f16c,-avx512bitalg,-rdpru,+clwb,+mmx,+sse2,+rdseed,-avx512vbmi2,-prefetchi,-rdpid,-fma4,-avx512vbmi,-shstk,-vaes,-waitpkg,-sgx,+fxsr,+avx512dq,-sse4a,-avx512f <source>
1.	Running pass "function(loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>)" on module "<source>"
2.	Running pass "loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>" on function "wombat"
 #0 0x0000000004f053c8 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4f053c8)
 #1 0x0000000004f02b3c SignalHandler(int) Signals.cpp:0:0
 #2 0x00007458cc042520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x00007458cc0969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x00007458cc042476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x00007458cc0287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x00007458cc02871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
 #7 0x00007458cc039e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
 #8 0x0000000003f83f37 llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x3f83f37)
 #9 0x0000000003f86659 llvm::LoopVectorizePass::runImpl(llvm::Function&, llvm::ScalarEvolution&, llvm::LoopInfo&, llvm::TargetTransformInfo&, llvm::DominatorTree&, llvm::BlockFrequencyInfo*, llvm::TargetLibraryInfo*, llvm::DemandedBits&, llvm::AssumptionCache&, llvm::LoopAccessInfoManager&, llvm::OptimizationRemarkEmitter&, llvm::ProfileSummaryInfo*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x3f86659)
#10 0x0000000003f86cd2 llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x3f86cd2)
#11 0x0000000002e596ce llvm::detail::PassModel<llvm::Function, llvm::LoopVectorizePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x2e596ce)
#12 0x0000000004d02758 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4d02758)
#13 0x0000000000de089e llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xde089e)
#14 0x0000000004d0114e llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4d0114e)
#15 0x0000000000de0eee llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xde0eee)
#16 0x0000000004cff2b0 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4cff2b0)
#17 0x00000000008e3752 llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::ArrayRef<std::function<void (llvm::PassBuilder&)>>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8e3752)
#18 0x00000000008d667c optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8d667c)
#19 0x00007458cc029d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#20 0x00007458cc029e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#21 0x00000000008cdade _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8cdade)
Program terminated with signal: SIGSEGV
Compiler returned: 139
```

Potentially related: https://github.com/llvm/llvm-project/issues/100591


commit e577f14b670ee2ae6bb717133310b215be4331b3
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Fri Nov 1 22:18:44 2024 +0800

    [InstCombine] Use `m_NotForbidPoison` when folding `(X u< Y) ? -1 : (~X + Y) --> uadd.sat(~X, Y)` (#114345)

    Alive2: https://alive2.llvm.org/ce/z/mTGCo-
    We cannot reuse `~X` if `m_AllOnes` matches a vector constant with some
    poison elts. An alternative solution is to create a new not instead of
    reusing `~X`. But it doesn't worth the effort because we need to add a
    one-use check.

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

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 162ebebf1b8f..999ad1adff20 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1056,7 +1056,7 @@ static Value *canonicalizeSaturatedAdd(ICmpInst *Cmp, Value *TVal, Value *FVal,
   // Strictness of the comparison is irrelevant.
   X = Cmp0;
   Y = Cmp1;
-  if (match(FVal, m_c_Add(m_Not(m_Specific(X)), m_Specific(Y)))) {
+  if (match(FVal, m_c_Add(m_NotForbidPoison(m_Specific(X)), m_Specific(Y)))) {
     // (X u< Y) ? -1 : (~X + Y) --> uadd.sat(~X, Y)
     // (X u< Y) ? -1 : (Y + ~X) --> uadd.sat(Y, ~X)
     BinaryOperator *BO = cast<BinaryOperator>(FVal);

define i32 @uadd_sat_not_commute_select(i32 %x, i32 %y) {
  %notx = xor i32 %x, -1
  %a = add i32 %notx, %y
  %c = icmp ult i32 %y, %x
  %r = select i1 %c, i32 %a, i32 -1
  ret i32 %r
}

define <2 x i32> @uadd_sat_not_ugt_commute_add_partial_poison(<2 x i32> %x, <2 x i32> %yp) {
  %notx = xor <2 x i32> %x, <i32 -1, i32 poison>
  %a = add nuw <2 x i32> %yp, %notx
  %c = icmp ugt <2 x i32> %yp, %x
  %r = select <2 x i1> %c, <2 x i32> splat (i32 -1), <2 x i32> %a
  ret <2 x i32> %r
}

Poison value wrongly propagates through vector operations on an optimized code

https://github.com/llvm/llvm-project/blob/5d4a0d54b5269bad1410e6db957836fe98634069/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp#L1050-L1060

Alive2 report: https://alive2.llvm.org/ce/z/6tSdhb

```llvm
----------------------------------------
define <2 x i32> @uadd_sat_not_ugt_commute_add.2(<2 x i32> %x, <2 x i32> %yp) {
#0:
  %#1 = sdiv <2 x i32> { 2442, 4242 }, %yp
  %notx = xor <2 x i32> %x, { 4294967295, poison }
  %a = add nuw <2 x i32> %#1, %notx
  %c = icmp ugt <2 x i32> %#1, %x
  %r = select <2 x i1> %c, <2 x i32> { 4294967295, 4294967295 }, <2 x i32> %a
  ret <2 x i32> %r
}
=>
define <2 x i32> @uadd_sat_not_ugt_commute_add.2(<2 x i32> %x, <2 x i32> %yp) {
#0:
  %#1 = sdiv <2 x i32> { 2442, 4242 }, %yp
  %notx = xor <2 x i32> %x, { 4294967295, poison }
  %r = uadd_sat <2 x i32> %#1, %notx
  ret <2 x i32> %r
}
Transformation doesn't verify!

ERROR: Target is more poisonous than source

Example:
<2 x i32> %x = < poison, #x00000000 (0) >
<2 x i32> %yp = < #x00000008 (8), #x0000000e (14) >

Source:
<2 x i32> %#1 = < #x00000131 (305), #x0000012f (303) >
<2 x i32> %notx = < poison, poison >
<2 x i32> %a = < poison, poison >
<2 x i1> %c = < poison, #x1 (1) >
<2 x i32> %r = < poison, #xffffffff (4294967295, -1) >

Target:
<2 x i32> %#1 = < #x00000131 (305), #x0000012f (303) >
<2 x i32> %notx = < poison, poison >
<2 x i32> %r = < poison, poison >
Source value: < poison, #xffffffff (4294967295, -1) >
Target value: < poison, poison >

Summary:
  0 correct transformations
  1 incorrect transformations
  0 failed-to-prove transformations
  0 Alive2 errors
```


commit 0dacba3ad1b5214ca35eda14987c0b76568a070e
Author: Florian Hahn <flo@fhahn.com>
Date:   Fri Feb 16 12:58:39 2024 +0000

    [VPlan] Handle truncating ICMPs in truncateToMinimalBWs.

    Update truncateToMinimalBitwidths to handle truncating ICMPs. For ICMPs,
    the new target type will be the same as the original type. In that case,
    only truncate the operands, but skip the extend. This is in line with
    what the original truncateToMinimalBitwidths did for compares.

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

diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
index 16855a9227a1..99198cfa9955 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
@@ -977,9 +977,6 @@ void VPlanTransforms::truncateToMinimalBitwidths(
       Type *OldResTy = TypeInfo.inferScalarType(ResultVPV);
       unsigned OldResSizeInBits = OldResTy->getScalarSizeInBits();
       assert(OldResTy->isIntegerTy() && "only integer types supported");
-      if (OldResSizeInBits == NewResSizeInBits)
-        continue;
-      assert(OldResSizeInBits > NewResSizeInBits && "Nothing to shrink?");
       (void)OldResSizeInBits;

       auto *NewResTy = IntegerType::get(Ctx, NewResSizeInBits);
@@ -990,11 +987,17 @@ void VPlanTransforms::truncateToMinimalBitwidths(
       if (auto *VPW = dyn_cast<VPRecipeWithIRFlags>(&R))
         VPW->dropPoisonGeneratingFlags();

-      // Extend result to original width.
-      auto *Ext = new VPWidenCastRecipe(Instruction::ZExt, ResultVPV, OldResTy);
-      Ext->insertAfter(&R);
-      ResultVPV->replaceAllUsesWith(Ext);
-      Ext->setOperand(0, ResultVPV);
+      if (OldResSizeInBits != NewResSizeInBits) {
+        // Extend result to original width.
+        auto *Ext =
+            new VPWidenCastRecipe(Instruction::ZExt, ResultVPV, OldResTy);
+        Ext->insertAfter(&R);
+        ResultVPV->replaceAllUsesWith(Ext);
+        Ext->setOperand(0, ResultVPV);
+        assert(OldResSizeInBits > NewResSizeInBits && "Nothing to shrink?");
+      } else
+        assert(cast<VPWidenRecipe>(&R)->getOpcode() == Instruction::ICmp &&
+               "Only ICmps should not need extending the result.");

       if (isa<VPWidenMemoryInstructionRecipe>(&R)) {
         assert(!cast<VPWidenMemoryInstructionRecipe>(&R)->isStore() && "stores cannot be narrowed");

opt -passes=loop-vectorize,dce,instcombine -force-vector-interleave=1 -force-vector-width=8 -S < %s

define i32 @reduction_and_or(i16 %a, i32 %b, ptr %src) {
entry:
  %ext1 = zext i16 %a to i32
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
  %or67 = phi i32 [ 10, %entry ], [ %or, %loop ]
  %t = trunc i32 %b to i16
  %ext = sext i16 %t to i32
  %cmp = icmp sgt i32 %ext, %ext1
  %ext2 = zext i1 %cmp to i32
  %cmp3 = icmp sge i32 %iv, %ext2
  %ext4 = zext i1 %cmp3 to i32
  %div = sdiv i32 %ext4, %b
  %and = and i32 %div, 0
  %gep = getelementptr inbounds i32, ptr %src, i32 %iv
  %l = load i32, ptr %gep, align 4
  %add = add i32 %and, %l
  %or = or i32 %or67, %add
  %iv.next = add nsw i32 %iv, 1
  %tobool.not = icmp eq i32 %iv.next, 999
  br i1 %tobool.not, label %exit, label %loop

exit:                                             ; preds = %loop
  %or.lcssa = phi i32 [ %or, %loop ]
  ret i32 %or.lcssa
}

clang crashes at -O{s,2,3} on x86_64-linux-gnu: Assertion `MinBWs.size() == NumProcessedRecipes && "some entries in MinBWs haven't been processed"' failed

It appears to be a recent regression as it does not reproduce with 17.0.1 and earlier versions.

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

```
[511] % clangtk -v
clang version 19.0.0git (https://github.com/llvm/llvm-project.git 5932fcc47855fdd209784f38820422d2369b84b2)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /local/suz-local/opfuzz/bin
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
[512] %
[512] % clangtk -Os small.c
clang-19: /local/suz-local/software/clangbuild/llvm-project/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp:1038: static void llvm::VPlanTransforms::truncateToMinimalBitwidths(llvm::VPlan&, const llvm::MapVector<llvm::Instruction*, long unsigned int>&, llvm::LLVMContext&): Assertion `MinBWs.size() == NumProcessedRecipes && "some entries in MinBWs haven't been processed"' 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-19 -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/20240211-clangtk-m64-Os-Weverything-pipe-fPIC-build-024130/delta -fcoverage-compilation-dir=/local/suz-local/software/emitesting/bugs/20240211-clangtk-m64-Os-Weverything-pipe-fPIC-build-024130/delta -resource-dir /local/suz-local/software/local/clang-trunk/lib/clang/19 -I /usr/local/include -I /local/suz-local/software/local/include -internal-isystem /local/suz-local/software/local/clang-trunk/lib/clang/19/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-d74fff.o -x c small.c
1.	<eof> parser at end of file
2.	Optimizer
 #0 0x000055fb61397fcf llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x3f04fcf)
 #1 0x000055fb613954f4 SignalHandler(int) Signals.cpp:0:0
 #2 0x00007fdd88b17420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420)
 #3 0x00007fdd8851e00b raise /build/glibc-wuryBv/glibc-2.31/signal/../sysdeps/unix/sysv/linux/raise.c:51:1
 #4 0x00007fdd884fd859 abort /build/glibc-wuryBv/glibc-2.31/stdlib/abort.c:81:7
 #5 0x00007fdd884fd729 get_sysdep_segment_value /build/glibc-wuryBv/glibc-2.31/intl/loadmsgcat.c:509:8
 #6 0x00007fdd884fd729 _nl_load_domain /build/glibc-wuryBv/glibc-2.31/intl/loadmsgcat.c:970:34
 #7 0x00007fdd8850efd6 (/lib/x86_64-linux-gnu/libc.so.6+0x33fd6)
 #8 0x000055fb62c44895 llvm::VPlanTransforms::truncateToMinimalBitwidths(llvm::VPlan&, llvm::MapVector<llvm::Instruction*, unsigned long, llvm::DenseMap<llvm::Instruction*, unsigned int, llvm::DenseMapInfo<llvm::Instruction*, void>, llvm::detail::DenseMapPair<llvm::Instruction*, unsigned int>>, llvm::SmallVector<std::pair<llvm::Instruction*, unsigned long>, 0u>> const&, llvm::LLVMContext&) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x57b1895)
 #9 0x000055fb62b2644a llvm::LoopVectorizationPlanner::buildVPlansWithVPRecipes(llvm::ElementCount, llvm::ElementCount) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x569344a)
#10 0x000055fb62b2d861 llvm::LoopVectorizationPlanner::plan(llvm::ElementCount, unsigned int) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x569a861)
#11 0x000055fb62b30a1f llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x569da1f)
#12 0x000055fb62b33acd llvm::LoopVectorizePass::runImpl(llvm::Function&, llvm::ScalarEvolution&, llvm::LoopInfo&, llvm::TargetTransformInfo&, llvm::DominatorTree&, llvm::BlockFrequencyInfo*, llvm::TargetLibraryInfo*, llvm::DemandedBits&, llvm::AssumptionCache&, llvm::LoopAccessInfoManager&, llvm::OptimizationRemarkEmitter&, llvm::ProfileSummaryInfo*) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x56a0acd)
#13 0x000055fb62b34d20 llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x56a1d20)
#14 0x000055fb62717536 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-19+0x5284536)
#15 0x000055fb5ea6d61d 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-19+0x15da61d)
#16 0x000055fb60d5cb3d llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x38c9b3d)
#17 0x000055fb5ea509a6 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-19+0x15bd9a6)
#18 0x000055fb60d5aa6d llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x38c7a6d)
#19 0x000055fb6161dc90 (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
#20 0x000055fb61620f60 (anonymous namespace)::EmitAssemblyHelper::EmitAssembly(clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>, clang::BackendConsumer*) BackendUtil.cpp:0:0
#21 0x000055fb616215cb 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-19+0x418e5cb)
#22 0x000055fb61c5730a clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x47c430a)
#23 0x000055fb63944ee9 clang::ParseAST(clang::Sema&, bool, bool) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x64b1ee9)
#24 0x000055fb61c566a8 clang::CodeGenAction::ExecuteAction() (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x47c36a8)
#25 0x000055fb61ed4429 clang::FrontendAction::Execute() (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x4a41429)
#26 0x000055fb61e508de clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x49bd8de)
#27 0x000055fb61fb8d46 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x4b25d46)
#28 0x000055fb5e655986 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x11c2986)
#29 0x000055fb5e64cfba ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#30 0x000055fb5e652434 clang_main(int, char**, llvm::ToolContext const&) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x11bf434)
#31 0x000055fb5e564aab main (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x10d1aab)
#32 0x00007fdd884ff083 __libc_start_main /build/glibc-wuryBv/glibc-2.31/csu/../csu/libc-start.c:342:3
#33 0x000055fb5e64ca7e _start (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x11b9a7e)
clangtk: error: unable to execute command: Aborted
clangtk: error: clang frontend command failed due to signal (use -v to see invocation)
clang version 19.0.0git (https://github.com/llvm/llvm-project.git 5932fcc47855fdd209784f38820422d2369b84b2)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /local/suz-local/opfuzz/bin
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-ca7a0b.c
clangtk: note: diagnostic msg: /tmp/small-ca7a0b.sh
clangtk: note: diagnostic msg:

********************
[513] %
[513] % cat small.c
static int *a, **b = &a, f = 1;
int c, d, h;
short e, g;
int main() {
  int **i[9] = {&a, &a, &a, &a, &a, &a, &a, &a, &a};
  for (; d; d++)
    if ((**b < e) | f) {
      int *j = &f, k;
      c = h;
      k = g > ((long)j == 1);
    }
  return 0;
}
```

Another related test that reproduces the crash only at -Os.

```
[513] % clangtk -v
clang version 19.0.0git (https://github.com/llvm/llvm-project.git e769fb8699e3fa8e40623764f7713bfc783b0330)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /local/suz-local/opfuzz/bin
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
[514] %
[514] % clangtk -Os small.c
clang-19: /local/suz-local/software/clangbuild/llvm-project/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp:1038: static void llvm::VPlanTransforms::truncateToMinimalBitwidths(llvm::VPlan&, const llvm::MapVector<llvm::Instruction*, long unsigned int>&, llvm::LLVMContext&): Assertion `MinBWs.size() == NumProcessedRecipes && "some entries in MinBWs haven't been processed"' 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-19 -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/DUP/20240215-clangtk-m64-Os-Weverything-pipe-fPIC-build-144944/delta -fcoverage-compilation-dir=/local/suz-local/software/emitesting/bugs/DUP/20240215-clangtk-m64-Os-Weverything-pipe-fPIC-build-144944/delta -resource-dir /local/suz-local/software/local/clang-trunk/lib/clang/19 -I /usr/local/include -I /local/suz-local/software/local/include -internal-isystem /local/suz-local/software/local/clang-trunk/lib/clang/19/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-a3d3db.o -x c small.c
1.	<eof> parser at end of file
2.	Optimizer
 #0 0x000055bf09b51e2f llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x3f38e2f)
 #1 0x000055bf09b4f354 SignalHandler(int) Signals.cpp:0:0
 #2 0x00007fdb52bbc420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420)
 #3 0x00007fdb525c300b raise /build/glibc-wuryBv/glibc-2.31/signal/../sysdeps/unix/sysv/linux/raise.c:51:1
 #4 0x00007fdb525a2859 abort /build/glibc-wuryBv/glibc-2.31/stdlib/abort.c:81:7
 #5 0x00007fdb525a2729 get_sysdep_segment_value /build/glibc-wuryBv/glibc-2.31/intl/loadmsgcat.c:509:8
 #6 0x00007fdb525a2729 _nl_load_domain /build/glibc-wuryBv/glibc-2.31/intl/loadmsgcat.c:970:34
 #7 0x00007fdb525b3fd6 (/lib/x86_64-linux-gnu/libc.so.6+0x33fd6)
 #8 0x000055bf0b405565 llvm::VPlanTransforms::truncateToMinimalBitwidths(llvm::VPlan&, llvm::MapVector<llvm::Instruction*, unsigned long, llvm::DenseMap<llvm::Instruction*, unsigned int, llvm::DenseMapInfo<llvm::Instruction*, void>, llvm::detail::DenseMapPair<llvm::Instruction*, unsigned int>>, llvm::SmallVector<std::pair<llvm::Instruction*, unsigned long>, 0u>> const&, llvm::LLVMContext&) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x57ec565)
 #9 0x000055bf0b2e62ba llvm::LoopVectorizationPlanner::buildVPlansWithVPRecipes(llvm::ElementCount, llvm::ElementCount) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x56cd2ba)
#10 0x000055bf0b2ed661 llvm::LoopVectorizationPlanner::plan(llvm::ElementCount, unsigned int) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x56d4661)
#11 0x000055bf0b2f081f llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x56d781f)
#12 0x000055bf0b2f38cd llvm::LoopVectorizePass::runImpl(llvm::Function&, llvm::ScalarEvolution&, llvm::LoopInfo&, llvm::TargetTransformInfo&, llvm::DominatorTree&, llvm::BlockFrequencyInfo*, llvm::TargetLibraryInfo*, llvm::DemandedBits&, llvm::AssumptionCache&, llvm::LoopAccessInfoManager&, llvm::OptimizationRemarkEmitter&, llvm::ProfileSummaryInfo*) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x56da8cd)
#13 0x000055bf0b2f4b20 llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x56dbb20)
#14 0x000055bf0aed6086 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-19+0x52bd086)
#15 0x000055bf0721ff8d 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-19+0x1606f8d)
#16 0x000055bf0951611d llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x38fd11d)
#17 0x000055bf072032e6 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-19+0x15ea2e6)
#18 0x000055bf0951404d llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x38fb04d)
#19 0x000055bf09dd88c0 (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
#20 0x000055bf09ddbb80 (anonymous namespace)::EmitAssemblyHelper::EmitAssembly(clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>, clang::BackendConsumer*) BackendUtil.cpp:0:0
#21 0x000055bf09ddc1eb 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-19+0x41c31eb)
#22 0x000055bf0a41298a clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x47f998a)
#23 0x000055bf0c10e439 clang::ParseAST(clang::Sema&, bool, bool) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x64f5439)
#24 0x000055bf0a411d18 clang::CodeGenAction::ExecuteAction() (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x47f8d18)
#25 0x000055bf0a6903e9 clang::FrontendAction::Execute() (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x4a773e9)
#26 0x000055bf0a60d21e clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x49f421e)
#27 0x000055bf0a776736 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x4b5d736)
#28 0x000055bf06e06b76 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x11edb76)
#29 0x000055bf06dfe1aa ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#30 0x000055bf06e03624 clang_main(int, char**, llvm::ToolContext const&) (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x11ea624)
#31 0x000055bf06d15abb main (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x10fcabb)
#32 0x00007fdb525a4083 __libc_start_main /build/glibc-wuryBv/glibc-2.31/csu/../csu/libc-start.c:342:3
#33 0x000055bf06dfdc6e _start (/local/suz-local/software/local/clang-trunk/bin/clang-19+0x11e4c6e)
clangtk: error: unable to execute command: Aborted
clangtk: error: clang frontend command failed due to signal (use -v to see invocation)
clang version 19.0.0git (https://github.com/llvm/llvm-project.git e769fb8699e3fa8e40623764f7713bfc783b0330)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /local/suz-local/opfuzz/bin
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-585ede.c
clangtk: note: diagnostic msg: /tmp/small-585ede.sh
clangtk: note: diagnostic msg:

********************
[515] %
[515] % cat small.c
int a = 1, b, c, d;
short e() { return a == 1 ? a : a % b; }
static int f;
short g;
unsigned short h;
int main() {
  int *i[10] = {&f};
  for (c = -2; c; c++) {
    g = e();
    d |= f & ((b >= (g > h)) / a);
  }
  return 0;
}
```

Thanks for the test case, should be fixed!

It looks like this only gets triggered when the resulting truncated compare is dead. Please let me know if you see any issues with similar cases where the resulting loop/compares in the loop aren't dead.


commit 263224e4481b0850539a93a272184aac4abe86d4
Author: Nikita Popov <npopov@redhat.com>
Date:   Tue May 21 14:57:19 2024 +0200

    [InstCombine] Require poison operand in canEvaluateShuffled transform

    This transform works on single-source shuffles, which require that
    the second operand is poison, not undef. Otherwise we may convert
    undef to poison.

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

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
index 99f1f8eb34bb..745ccbfe9dc7 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
@@ -2901,7 +2901,7 @@ Instruction *InstCombinerImpl::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
   if (Instruction *I = foldIdentityPaddedShuffles(SVI))
     return I;

-  if (match(RHS, m_Undef()) && canEvaluateShuffled(LHS, Mask)) {
+  if (match(RHS, m_Poison()) && canEvaluateShuffled(LHS, Mask)) {
     Value *V = evaluateInDifferentElementOrder(LHS, Mask, Builder);
     return replaceInstUsesWith(SVI, V);
   }

define i16 @pr92887(<2 x i16> %v) {
  %v0 = extractelement <2 x i16> %v, i64 0
  %v0lo = and i16 %v0, 1
  %v1 = extractelement <2 x i16> %v, i64 1
  %v1lo = and i16 %v1, 1
  %ins1 = insertelement <4 x i16> poison, i16 %v0lo, i64 0
  %ins2 = insertelement <4 x i16> %ins1, i16 %v1lo, i64 1
  %shuf = shufflevector <4 x i16> %ins2, <4 x i16> <i16 poison, i16 poison, i16 undef, i16 undef>, <4 x i32> <i32 0, i32 1, i32 6, i32 7>
  %extract = extractelement <4 x i16> %shuf, i32 2
  ret i16 %extract
}

define <4 x i16> @blend_elements_from_load(ptr align 8 %_0) {
  %load = load <3 x i16>, ptr %_0, align 8
  %rv = shufflevector <3 x i16> <i16 0, i16 undef, i16 undef>, <3 x i16> %load, <4 x i32> <i32 0, i32 1, i32 3, i32 5>
  ret <4 x i16> %rv
}

Miscompile with opt -passes="instcombine"

llvm commit: 502bea25bdc07d1

Reproduce with:
```opt -passes="instcombine" bbi-95633_2.ll -S -o -```

Result:
```
define i16 @foo() {
entry:
  store i16 0, ptr @bit, align 2
  store i16 0, ptr getelementptr inbounds (i8, ptr @bit, i64 2), align 2
  store i16 0, ptr getelementptr inbounds (i8, ptr @bit, i64 4), align 2
  store i16 0, ptr getelementptr inbounds (i8, ptr @bit, i64 6), align 2
  store i16 2, ptr getelementptr inbounds (i8, ptr @bit, i64 8), align 2
  store i16 0, ptr getelementptr inbounds (i8, ptr @bit, i64 10), align 2
  ret i16 poison
}
```
Note the poison return value which I think is wrong.

Before commit e93d324adb4ff8
```
[InstCombine] Preserve poison in evaluateInDifferentElementOrder()

Don't unnecessarily replace poison with undef.
```
we instead got
```
define i16 @foo() {
entry:
  store i16 0, ptr @bit, align 2
  store i16 0, ptr getelementptr inbounds (%struct.bit, ptr @bit, i64 0, i32 1), align 2
  store i16 0, ptr getelementptr inbounds (%struct.bit, ptr @bit, i64 0, i32 2), align 2
  store i16 0, ptr getelementptr inbounds (%struct.bit, ptr @bit, i64 0, i32 3), align 2
  store i16 2, ptr getelementptr inbounds (%struct.bit, ptr @bit, i64 0, i32 4), align 2
  store i16 0, ptr getelementptr inbounds (%struct.bit, ptr @bit, i64 0, i32 5), align 2
  ret i16 1
}
```
where we return 1 instead of poison.

I tried to use Alive2 on the input/output in
 https://alive2.llvm.org/ce/z/1GVkRh
and it says
```
Transformation doesn't verify!

ERROR: Target is more poisonous than source
```

[bbi-95633_2.ll.gz](https://github.com/llvm/llvm-project/files/15387836/bbi-95633_2.ll.gz)

@nikic : Any idea about this?

Here's a reduced test case:

```llvm
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt -passes=instcombine -S %s | FileCheck %s

%struct.widget = type { i16, i16, i16, i16, i16, i16 }

; Miscompile. Correct output: 1, incorrect output: poison.
define i16 @pr92887(ptr %p, i16 %x, i16 %y) {
; CHECK-LABEL: define i16 @pr92887(
; CHECK-SAME: ptr [[P:%.*]], i16 [[X:%.*]], i16 [[Y:%.*]]) {
; CHECK-NEXT:    store i16 0, ptr [[P]], align 2
; CHECK-NEXT:    [[P_REPACK1:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 2
; CHECK-NEXT:    store i16 0, ptr [[P_REPACK1]], align 2
; CHECK-NEXT:    [[P_REPACK2:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 4
; CHECK-NEXT:    store i16 0, ptr [[P_REPACK2]], align 2
; CHECK-NEXT:    [[P_REPACK3:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 6
; CHECK-NEXT:    store i16 0, ptr [[P_REPACK3]], align 2
; CHECK-NEXT:    [[P_REPACK4:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8
; CHECK-NEXT:    store i16 2, ptr [[P_REPACK4]], align 2
; CHECK-NEXT:    [[P_REPACK5:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 10
; CHECK-NEXT:    store i16 0, ptr [[P_REPACK5]], align 2
; CHECK-NEXT:    ret i16 poison
;
  store %struct.widget { i16 0, i16 0, i16 0, i16 0, i16 2, i16 0 }, ptr %p
  %insert.y = insertelement <2 x i16> zeroinitializer, i16 %y, i64 0
  %insert.x = insertelement <2 x i16> %insert.y, i16 %x, i64 1
  %shufflevector = shufflevector <2 x i16> %insert.x, <2 x i16> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
  %extract = extractelement <4 x i16> %shufflevector, i32 2 ; undef
  %and = and i16 %extract, 0 ; 0
  %gep = getelementptr %struct.widget, ptr %p, i32 0, i32 4
  %load = load i16, ptr %gep ; 2
  %or = or i16 %and, %load ; 2
  %ashr = ashr i16 %or, 1 ; 1
  ret i16 %ashr ; 1
}
```

EDIT: Sorry, Alive2 verifies the transformation as correct.

The problematic transform is:
```llvm
define i16 @src(<2 x i16> %v) {
  %v0 = extractelement <2 x i16> %v, i64 0
  %v0lo = and i16 %v0, 1
  %v1 = extractelement <2 x i16> %v, i64 1
  %v1lo = and i16 %v1, 1
  %ins1 = insertelement <4 x i16> poison, i16 %v0lo, i64 0
  %ins2 = insertelement <4 x i16> %ins1, i16 %v1lo, i64 1
  %shuf = shufflevector <4 x i16> %ins2, <4 x i16> <i16 poison, i16 poison, i16 undef, i16 undef>, <4 x i32> <i32 0, i32 1, i32 6, i32 7>
  %extract = extractelement <4 x i16> %shuf, i32 2
  ret i16 %extract
}
```
To:
```
define i16 @src(<2 x i16> %v) {
  %v0 = extractelement <2 x i16> %v, i64 0
  %v0lo = and i16 %v0, 1
  %v1 = extractelement <2 x i16> %v, i64 1
  %v1lo = and i16 %v1, 1
  %1 = insertelement <4 x i16> poison, i16 %v0lo, i64 0
  %shuf = insertelement <4 x i16> %1, i16 %v1lo, i64 1
  %extract = extractelement <4 x i16> %shuf, i32 2
  ret i16 %extract
}
```

At a glance, the problem is likely that https://github.com/llvm/llvm-project/blob/e93d324adb4ff80dcbf0e5b678ed3342350eb2de/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp#L2881 should be matching m_Poison, not m_Undef, otherwise it's not a real single-source shuffle.

Thanks for the quick fix!
I've verified that it solves the problem we saw.

As a bonus, fixed a similar miscompile in https://github.com/llvm/llvm-project/commit/ecd269e8305330c185bbedbd5a59e887122333ba.

Another one in https://github.com/llvm/llvm-project/commit/8f1c984325bd679b2634a6173db69548da87ac71.

And... one more in https://github.com/llvm/llvm-project/commit/d0e0205bfc5a147f8744a176a10f185af7520c26.

Nice, four fixes from just one issue! :)