commit 3bd161e98d89d31696002994771b7761f1c74859
Author: Florian Hahn <flo@fhahn.com>
Date:   Tue Sep 3 21:06:31 2024 +0100

    [LV] Honor forced scalars in setVectorizedCallDecision.

    Similarly to dd94537b4, setVectorizedCallDecision also did not consider
    ForcedScalars. This lead to VPlans not reflecting the decision by the
    legacy cost model (cost computation would use scalar cost, VPlan would
    have VPWidenCallRecipe).

    To fix this, check if the call has been forced to scalar in
    setVectorizedCallDecision.

    Note that this requires moving setVectorizedCallDecision after
    collectLoopUniforms (which sets ForcedScalars). collectLoopUniforms does
    not depend on call decisions and can safely be moved.

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

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 17050b2b433c..0200525a718d 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -1290,8 +1290,8 @@ public:
     if (VF.isScalar() || Uniforms.contains(VF))
       return;
     setCostBasedWideningDecision(VF);
-    setVectorizedCallDecision(VF);
     collectLoopUniforms(VF);
+    setVectorizedCallDecision(VF);
     collectLoopScalars(VF);
   }

@@ -6194,6 +6194,7 @@ void LoopVectorizationCostModel::setVectorizedCallDecision(ElementCount VF) {
   assert(!VF.isScalar() &&
          "Trying to set a vectorization decision for a scalar VF");

+  auto ForcedScalar = ForcedScalars.find(VF);
   for (BasicBlock *BB : TheLoop->blocks()) {
     // For each instruction in the old loop.
     for (Instruction &I : *BB) {
@@ -6206,14 +6207,37 @@ void LoopVectorizationCostModel::setVectorizedCallDecision(ElementCount VF) {
       InstructionCost VectorCost = InstructionCost::getInvalid();
       InstructionCost IntrinsicCost = InstructionCost::getInvalid();
       TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
-
       Function *ScalarFunc = CI->getCalledFunction();
       Type *ScalarRetTy = CI->getType();
       SmallVector<Type *, 4> Tys, ScalarTys;
-      bool MaskRequired = Legal->isMaskRequired(CI);
       for (auto &ArgOp : CI->args())
         ScalarTys.push_back(ArgOp->getType());

+      // Estimate cost of scalarized vector call. The source operands are
+      // assumed to be vectors, so we need to extract individual elements from
+      // there, execute VF scalar calls, and then gather the result into the
+      // vector return value.
+      InstructionCost ScalarCallCost =
+          TTI.getCallInstrCost(ScalarFunc, ScalarRetTy, ScalarTys, CostKind);
+
+      // Compute costs of unpacking argument values for the scalar calls and
+      // packing the return values to a vector.
+      InstructionCost ScalarizationCost =
+          getScalarizationOverhead(CI, VF, CostKind);
+
+      ScalarCost = ScalarCallCost * VF.getKnownMinValue() + ScalarizationCost;
+      // Honor ForcedScalars decision.
+      // TODO: For calls, it might still be more profitable to widen. Use
+      // VPlan-based cost model to compare different options.
+      if (VF.isVector() && ForcedScalar != ForcedScalars.end() &&
+          ForcedScalar->second.contains(CI)) {
+        setCallWideningDecision(CI, VF, CM_Scalarize, nullptr,
+                                Intrinsic::not_intrinsic, std::nullopt,
+                                ScalarCost);
+        continue;
+      }
+
+      bool MaskRequired = Legal->isMaskRequired(CI);
       // Compute corresponding vector type for return value and arguments.
       Type *RetTy = ToVectorTy(ScalarRetTy, VF);
       for (Type *ScalarTy : ScalarTys)
@@ -6229,20 +6253,6 @@ void LoopVectorizationCostModel::setVectorizedCallDecision(ElementCount VF) {
           continue;
         }

-      // Estimate cost of scalarized vector call. The source operands are
-      // assumed to be vectors, so we need to extract individual elements from
-      // there, execute VF scalar calls, and then gather the result into the
-      // vector return value.
-      InstructionCost ScalarCallCost =
-          TTI.getCallInstrCost(ScalarFunc, ScalarRetTy, ScalarTys, CostKind);
-
-      // Compute costs of unpacking argument values for the scalar calls and
-      // packing the return values to a vector.
-      InstructionCost ScalarizationCost =
-          getScalarizationOverhead(CI, VF, CostKind);
-
-      ScalarCost = ScalarCallCost * VF.getKnownMinValue() + ScalarizationCost;
-
       // Find the cost of vectorizing the call, if we can find a suitable
       // vector variant of the function.
       bool UsesMask = false;

target triple = "arm64-apple-macosx11.0.0"

define void @call_forced_scalar(ptr %src.1, ptr %src.2, ptr noalias %dst.1, ptr noalias %dst.2) {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %0 = load i32, ptr %src.1, align 4
  %smax = tail call i32 @llvm.smax.i32(i32 %0, i32 0)
  %umin = tail call i32 @llvm.umin.i32(i32 %smax, i32 1)
  %umin.ext = zext i32 %umin to i64
  %gep.src.2 = getelementptr i8, ptr %src.2, i64 %umin.ext
  %1 = load i8, ptr %gep.src.2, align 1
  %l.ext = zext i8 %1 to i32
  %mul = mul i32 3, %l.ext
  store i32 %mul, ptr %dst.1, align 4
  %gep.dst.2 = getelementptr i32, ptr %dst.2, i64 %iv
  store i32 0, ptr %gep.dst.2, align 4
  %iv.next = add i64 %iv, 1
  %ec = icmp eq i64 %iv.next, 0
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop
  ret void
}

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

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

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

target triple = "arm64-apple-macosx11.0.0"

define void @call_scalarized(ptr noalias %src, ptr noalias %dst, double %0) {
entry:
  br label %loop.header

loop.header:                                      ; preds = %loop.latch, %entry
  %iv = phi i64 [ 100, %entry ], [ %iv.next, %loop.latch ]
  %iv.next = add i64 %iv, -1
  %gep.src = getelementptr double, ptr %src, i64 %iv.next
  %l = load double, ptr %gep.src, align 8
  %cmp295 = fcmp ugt double %0, 0.000000e+00
  %cmp299 = fcmp ugt double %l, 0.000000e+00
  %or.cond = or i1 %cmp295, %cmp299
  br i1 %or.cond, label %loop.latch, label %then

then:                                             ; preds = %loop.header
  %sqrt = call double @llvm.sqrt.f64(double %l)
  %gep.dst = getelementptr double, ptr %dst, i64 %iv.next
  store double %sqrt, ptr %gep.dst, align 8
  br label %loop.latch

loop.latch:                                       ; preds = %then, %loop.header
  %tobool.not = icmp eq i64 %iv.next, 0
  br i1 %tobool.not, label %exit, label %loop.header

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

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

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

target triple = "arm64-apple-macosx11.0.0"

define void @fshl_operand_first_order_recurrence(ptr %dst, ptr noalias %src) {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %recur = phi i64 [ 0, %entry ], [ %l, %loop ]
  %gep.src = getelementptr inbounds i64, ptr %src, i64 %iv
  %l = load i64, ptr %gep.src, align 8
  %or = tail call i64 @llvm.fshl.i64(i64 1, i64 %recur, i64 1)
  %gep.dst = getelementptr inbounds i64, ptr %dst, i64 %iv
  store i64 %or, ptr %gep.dst, align 8
  %iv.next = add i64 %iv, 1
  %exitcond.not = icmp eq i64 %iv, 100
  br i1 %exitcond.not, label %exit, label %loop

exit:                                             ; preds = %loop
  ret void
}

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

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

target triple = "arm64-apple-macosx11.0.0"

define void @powi_call(ptr %P) {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %gep = getelementptr inbounds double, ptr %P, i64 %iv
  %l = load double, ptr %gep, align 8
  %powi = tail call double @llvm.powi.f64.i32(double %l, i32 3)
  store double %powi, ptr %gep, align 8
  %iv.next = add i64 %iv, 1
  %ec = icmp eq i64 %iv, 1
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop
  ret void
}

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

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

[clang] Assertion failed in Vectorize

I compiled this code with -Os and a crash appeared in assertion failure:

```c
#include <stdint.h>
int32_t *c;
int8_t ****d;
uint64_t g;
int a();
long b(long, long h, long p3) {
  long e;
  int f = 0;
  if (h) {
    e = h;
    f = 1;
  }
  if (e > p3)
    f = 2;
  switch (f) {
  case 1:
    e++;
  case 2:
    e--;
  }
  if (e < h)
    e = h;
  return e;
}

uint8_t div_func_uint8_t_u_u(uint8_t ui1, uint8_t ui2)
{
  return (ui1 / ui2);
}

uint64_t j() {
  uint16_t k[8];
  int i;
  for (i = 0; *c + ****d + (int)g + i < 8; i++)
    k[b(0, g, 0)] = 6;
  *c = div_func_uint8_t_u_u(k[6], a());
}
```

The crash is:
```
clang: /root/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:7369: llvm::VectorizationFactor llvm::LoopVectorizationPlanner::computeBestVF(): Assertion `(BestFactor.Width == LegacyVF.Width || planContainsAdditionalSimplifications(getPlanFor(BestFactor.Width), CostCtx, OrigLoop)) && " VPlan cost model and legacy cost model disagreed"' failed.
```

Details can be found here: https://godbolt.org/z/T81adKPY5

Unreduced LLVM IR:
```llvm ir
; ModuleID = '/app/example.c'
source_filename = "/app/example.c"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

@c = dso_local local_unnamed_addr global ptr null, align 8
@d = dso_local local_unnamed_addr global ptr null, align 8
@g = dso_local local_unnamed_addr global i64 0, align 8

; Function Attrs: mustprogress nofree norecurse nosync nounwind optsize willreturn memory(none) uwtable
define dso_local i64 @b(i64 noundef %0, i64 noundef %h, i64 noundef %p3) local_unnamed_addr #0 {
entry:
  %tobool.not = icmp ne i64 %h, 0
  %spec.select = zext i1 %tobool.not to i32
  %cmp = icmp sgt i64 %h, %p3
  %f.1 = select i1 %cmp, i32 2, i32 %spec.select
  switch i32 %f.1, label %sw.epilog [
    i32 1, label %sw.bb
    i32 2, label %sw.bb3
  ]

sw.bb:                                            ; preds = %entry
  %inc = add nsw i64 %h, 1
  br label %sw.bb3

sw.bb3:                                           ; preds = %entry, %sw.bb
  %e.1 = phi i64 [ %h, %entry ], [ %inc, %sw.bb ]
  %dec = add nsw i64 %e.1, -1
  br label %sw.epilog

sw.epilog:                                        ; preds = %sw.bb3, %entry
  %e.2 = phi i64 [ %h, %entry ], [ %dec, %sw.bb3 ]
  %spec.select14 = tail call i64 @llvm.smax.i64(i64 %e.2, i64 %h)
  ret i64 %spec.select14
}

; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #1

; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #1

; Function Attrs: mustprogress nofree norecurse nosync nounwind optsize willreturn memory(none) uwtable
define dso_local noundef zeroext i8 @div_func_uint8_t_u_u(i8 noundef zeroext %ui1, i8 noundef zeroext %ui2) local_unnamed_addr #0 {
entry:
  %0 = udiv i8 %ui1, %ui2
  ret i8 %0
}

; Function Attrs: nounwind optsize uwtable
define dso_local i64 @j() local_unnamed_addr #2 {
entry:
  %k = alloca [8 x i16], align 16
  call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %k) #5
  %0 = load ptr, ptr @c, align 8, !tbaa !6
  %1 = load i32, ptr %0, align 4, !tbaa !10
  %2 = load ptr, ptr @d, align 8, !tbaa !6
  %3 = load ptr, ptr %2, align 8, !tbaa !6
  %4 = load ptr, ptr %3, align 8, !tbaa !6
  %5 = load ptr, ptr %4, align 8, !tbaa !6
  %6 = load i8, ptr %5, align 1, !tbaa !12
  %conv = sext i8 %6 to i32
  %7 = load i64, ptr @g, align 8, !tbaa !13
  %conv1 = trunc i64 %7 to i32
  %invariant.op = add i32 %conv, %conv1
  %add3.reass12 = add i32 %1, %invariant.op
  %cmp13 = icmp slt i32 %add3.reass12, 8
  br i1 %cmp13, label %for.body.lr.ph, label %for.end

for.body.lr.ph:                                   ; preds = %entry
  %tobool.not.i = icmp ne i64 %7, 0
  %spec.select.i = zext i1 %tobool.not.i to i32
  %cmp.i = icmp sgt i64 %7, 0
  %f.1.i = select i1 %cmp.i, i32 2, i32 %spec.select.i
  %inc.i = add nsw i64 %7, 1
  br label %for.body

for.body:                                         ; preds = %for.body.lr.ph, %b.exit
  %i.014 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %b.exit ]
  switch i32 %f.1.i, label %b.exit [
    i32 1, label %sw.bb.i
    i32 2, label %sw.bb3.i
  ]

sw.bb.i:                                          ; preds = %for.body
  br label %sw.bb3.i

sw.bb3.i:                                         ; preds = %sw.bb.i, %for.body
  %e.1.i = phi i64 [ %7, %for.body ], [ %inc.i, %sw.bb.i ]
  %dec.i = add nsw i64 %e.1.i, -1
  br label %b.exit

b.exit:                                           ; preds = %for.body, %sw.bb3.i
  %e.2.i = phi i64 [ %7, %for.body ], [ %dec.i, %sw.bb3.i ]
  %spec.select14.i = tail call i64 @llvm.smax.i64(i64 %e.2.i, i64 %7)
  %arrayidx = getelementptr inbounds [8 x i16], ptr %k, i64 0, i64 %spec.select14.i
  store i16 6, ptr %arrayidx, align 2, !tbaa !15
  %inc = add nuw nsw i32 %i.014, 1
  %add = add i32 %1, %inc
  %add3.reass = add i32 %add, %invariant.op
  %cmp = icmp slt i32 %add3.reass, 8
  br i1 %cmp, label %for.body, label %for.end.loopexit, !llvm.loop !17

for.end.loopexit:                                 ; preds = %b.exit
  %arrayidx5.phi.trans.insert = getelementptr inbounds i8, ptr %k, i64 12
  %.pre = load i16, ptr %arrayidx5.phi.trans.insert, align 4, !tbaa !15
  %8 = trunc i16 %.pre to i8
  br label %for.end

for.end:                                          ; preds = %for.end.loopexit, %entry
  %conv6 = phi i8 [ %8, %for.end.loopexit ], [ undef, %entry ]
  %call7 = tail call i32 (...) @a() #6
  %conv8 = trunc i32 %call7 to i8
  %9 = udiv i8 %conv6, %conv8
  %conv10 = zext i8 %9 to i32
  %10 = load ptr, ptr @c, align 8, !tbaa !6
  store i32 %conv10, ptr %10, align 4, !tbaa !10
  call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %k) #5
  ret i64 undef
}

; Function Attrs: optsize
declare i32 @a(...) local_unnamed_addr #3

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i64 @llvm.smax.i64(i64, i64) #4

attributes #0 = { mustprogress nofree norecurse nosync nounwind optsize willreturn memory(none) uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #1 = { mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
attributes #2 = { nounwind optsize uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #3 = { optsize "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #4 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
attributes #5 = { nounwind }
attributes #6 = { nounwind optsize }

!llvm.module.flags = !{!0, !1, !2, !3, !4}
!llvm.ident = !{!5}

!0 = !{i32 7, !"Dwarf Version", i32 4}
!1 = !{i32 1, !"wchar_size", i32 4}
!2 = !{i32 8, !"PIC Level", i32 2}
!3 = !{i32 7, !"PIE Level", i32 2}
!4 = !{i32 7, !"uwtable", i32 2}
!5 = !{!"clang version 20.0.0git (https://github.com/llvm/llvm-project.git b6597f521d8a040f2b9fee54b3f89c380de8e432)"}
!6 = !{!7, !7, i64 0}
!7 = !{!"any pointer", !8, i64 0}
!8 = !{!"omnipotent char", !9, i64 0}
!9 = !{!"Simple C/C++ TBAA"}
!10 = !{!11, !11, i64 0}
!11 = !{!"int", !8, i64 0}
!12 = !{!8, !8, i64 0}
!13 = !{!14, !14, i64 0}
!14 = !{!"long", !8, i64 0}
!15 = !{!16, !16, i64 0}
!16 = !{!"short", !8, i64 0}
!17 = distinct !{!17, !18}
!18 = !{!"llvm.loop.mustprogress"}
```

https://godbolt.org/z/Yo1crEjGG

cc @fhahn


commit ba8126b6fef79bd344a247f6291aaec7b67bdff0
Author: Florian Hahn <flo@fhahn.com>
Date:   Wed Jul 24 09:31:32 2024 +0100

    [LV] Mark dead instructions in loop as free.

    Update collectValuesToIgnore to also ignore dead instructions in the
    loop. Such instructions will be removed by VPlan-based DCE and won't be
    considered by the VPlan-based cost model.

    This closes a gap between the legacy and VPlan-based cost model. In
    practice with the default pipelines, there shouldn't be any dead
    instructions in loops reaching LoopVectorize, but it is easy to generate
    such cases by hand or automatically via fuzzers.

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

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 8fa1a57177d9..e4477f96aa62 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -137,6 +137,7 @@
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "llvm/Transforms/Utils/InjectTLIMappings.h"
+#include "llvm/Transforms/Utils/Local.h"
 #include "llvm/Transforms/Utils/LoopSimplify.h"
 #include "llvm/Transforms/Utils/LoopUtils.h"
 #include "llvm/Transforms/Utils/LoopVersioning.h"
@@ -6681,6 +6682,7 @@ void LoopVectorizationCostModel::collectValuesToIgnore() {
   CodeMetrics::collectEphemeralValues(TheLoop, AC, ValuesToIgnore);

   SmallVector<Value *, 4> DeadInterleavePointerOps;
+  SmallVector<Value *, 4> DeadOps;
   for (BasicBlock *BB : TheLoop->blocks())
     for (Instruction &I : *BB) {
       // Find all stores to invariant variables. Since they are going to sink
@@ -6690,6 +6692,17 @@ void LoopVectorizationCostModel::collectValuesToIgnore() {
           Legal->isInvariantAddressOfReduction(SI->getPointerOperand()))
         ValuesToIgnore.insert(&I);

+      if (VecValuesToIgnore.contains(&I) || ValuesToIgnore.contains(&I))
+        continue;
+
+      // Add instructions that would be trivially dead and are only used by
+      // values already ignored to DeadOps to seed worklist.
+      if (wouldInstructionBeTriviallyDead(&I, TLI) &&
+          all_of(I.users(), [this](User *U) {
+            return VecValuesToIgnore.contains(U) || ValuesToIgnore.contains(U);
+          }))
+        DeadOps.push_back(&I);
+
       // For interleave groups, we only create a pointer for the start of the
       // interleave group. Queue up addresses of group members except the insert
       // position for further processing.
@@ -6717,6 +6730,29 @@ void LoopVectorizationCostModel::collectValuesToIgnore() {
     DeadInterleavePointerOps.append(Op->op_begin(), Op->op_end());
   }

+  // Mark ops that would be trivially dead and are only used by ignored
+  // instructions as free.
+  for (unsigned I = 0; I != DeadOps.size(); ++I) {
+    auto *Op = dyn_cast<Instruction>(DeadOps[I]);
+    // Skip any op that shouldn't be considered dead.
+    if (!Op || !TheLoop->contains(Op) ||
+        !wouldInstructionBeTriviallyDead(Op, TLI) ||
+        any_of(Op->users(), [this](User *U) {
+          return !VecValuesToIgnore.contains(U) && !ValuesToIgnore.contains(U);
+        }))
+      continue;
+
+    // If all of Op's users are in ValuesToIgnore, add it to ValuesToIgnore
+    // which applies for both scalar and vector versions. Otherwise it is only
+    // dead in vector versions, so only add it to VecValuesToIgnore.
+    if (all_of(Op->users(),
+               [this](User *U) { return ValuesToIgnore.contains(U); }))
+      ValuesToIgnore.insert(Op);
+
+    VecValuesToIgnore.insert(Op);
+    DeadOps.append(Op->op_begin(), Op->op_end());
+  }
+
   // Ignore type-promoting instructions we identified during reduction
   // detection.
   for (const auto &Reduction : Legal->getReductionVars()) {

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

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

; Test with a dead load in the loop, from
; https://github.com/llvm/llvm-project/issues/99701
define void @dead_load(ptr %p, i16 %start) {
;
entry:
  %start.ext = sext i16 %start to i64
  br label %loop

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

exit:
  ret void
}
;.
;.

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

I have a few finds by the fuzzer that affect LLVM (tested using a1d77caaabbb5279b734c061dab36b2138ec476d).
I think they're all duplicates but I'm attaching them all in a .zip so it can be confirmed.

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

define void @e(i64 %0) #0 {
entry:
  br label %for.body

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

for.body:                                         ; preds = %for.body, %entry
  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
  %arrayidx = getelementptr i16, ptr null, i64 %indvars.iv
  %1 = load i16, ptr %arrayidx, align 2
  %arrayidx5 = getelementptr [0 x i8], ptr null, i64 0, i64 %indvars.iv
  store i8 0, ptr %arrayidx5, align 1
  %indvars.iv.next = add nsw i64 %indvars.iv, 4
  %cmp = icmp ult i64 %indvars.iv, %0
  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,+zvl32b,+zvl64b,-b,-e,-experimental-smmpm,-experimental-smnpm,-experimental-ssnpm,-experimental-sspm,-experimental-ssqosid,-experimental-supm,-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,-zacas,-zalrsc,-zama16b,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmop,-zcmp,-zcmt,-zdinx,-zfa,-zfbfmin,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zihintntl,-zihintpause,-zihpm,-zimop,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-ztso,-zvbb,-zvbc,-zvfbfmin,-zvfbfwma,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl4096b,-zvl512b,-zvl65536b,-zvl8192b" }

```

Command/backtrace:
```bash
> /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:10444: bool llvm::LoopVectorizePass::processLoop(llvm::Loop*): Assertion `VF.Width == 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.
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 0x000055b365fe4a60 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2f0ea60)
 #1 0x000055b365fe1e7f llvm::sys::RunSignalHandlers() (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2f0be7f)
 #2 0x000055b365fe1fd5 SignalHandler(int) Signals.cpp:0:0
 #3 0x00007612a3042520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #4 0x00007612a30969fc __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #5 0x00007612a30969fc __pthread_kill_internal ./nptl/pthread_kill.c:78:10
 #6 0x00007612a30969fc pthread_kill ./nptl/pthread_kill.c:89:10
 #7 0x00007612a3042476 gsignal ./signal/../sysdeps/posix/raise.c:27:6
 #8 0x00007612a30287f3 abort ./stdlib/abort.c:81:7
 #9 0x00007612a302871b _nl_load_domain ./intl/loadmsgcat.c:1177:9
#10 0x00007612a3039e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
#11 0x000055b365005ba8 llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x1f2fba8)
#12 0x000055b365008761 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*) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x1f32761)
#13 0x000055b365008ee0 llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x1f32ee0)
#14 0x000055b363e81296 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+0xdab296)
#15 0x000055b365dfd4be 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+0x2d274be)
#16 0x000055b363e84426 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+0xdae426)
#17 0x000055b365dfc24b llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2d2624b)
#18 0x000055b363e80776 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+0xdaa776)
#19 0x000055b365dfa39d 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+0x2d2439d)
#20 0x000055b3636cbdc6 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+0x5f5dc6)
#21 0x000055b3636bda11 optMain (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x5e7a11)
#22 0x00007612a3029d90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#23 0x00007612a3029e40 call_init ./csu/../csu/libc-start.c:128:20
#24 0x00007612a3029e40 __libc_start_main ./csu/../csu/libc-start.c:379:5
#25 0x000055b3636b3855 _start (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x5dd855)
zsh: IOT instruction  /scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt
```

Godbolt: https://godbolt.org/z/a7KPnMh94

Zip with all finds reduced:
[finds.zip](https://github.com/user-attachments/files/16316789/finds.zip)

Related: https://github.com/llvm/llvm-project/pull/92555 @fhahn

Found via fuzzer.

I'm seeing this as well with a multitude of hits with csmith. One reduced test case:

clang -O3 -march=z16 crash0.i -o a.out -w -mllvm -disable-licm-promotion -mllvm -force-target-instruction-cost=1 -mllvm -unroll-count=4
LoopVectorize.cpp:10071: bool llvm::LoopVectorizePass::processLoop(llvm::Loop*): Assertion `VF.Width == Width && "VPlan cost model and legacy cost model disagreed"' failed.
#9 0x0000000004749e30 llvm::LoopVectorizePass::processLoop()

[tc_lv.i.tar.gz](https://github.com/user-attachments/files/16337463/tc_lv.i.tar.gz)

Thanks @patrick-rivos, it looks like all test cases had dead instructions, which would be considered by the legacy cost model but not the VPlan-based one (because VPlan-based DCE would clean them up before). Should be fixed now.

@JonPsson1's case was a different issue and should also be fixed.


commit 8df64ed77727ab9b7540819f2fe64379e88a50be
Author: Florian Hahn <flo@fhahn.com>
Date:   Sun Jan 12 22:03:21 2025 +0000

    [LV] Don't consider IV increments uniform if exit value is used outside.

    In some cases, there might be a chain of uniform instructions producing
    the exit value. To generate correct code in all cases, consider the IV
    increment not uniform, if there are users outside the loop.

    Instead, let VPlan narrow the IV, if possible using the logic from
    3ff1d01985752.

    Test case from #122602 verified with Alive2:
        https://alive2.llvm.org/ce/z/bA4EGj

    Fixes https://github.com/llvm/llvm-project/issues/122496.
    Fixes https://github.com/llvm/llvm-project/issues/122602.

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index b017b61a45a0..d32a463a996c 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -3806,7 +3806,7 @@ void LoopVectorizationCostModel::collectLoopUniforms(ElementCount VF) {
     // uniform after vectorization.
     bool UniformIndUpdate = all_of(IndUpdate->users(), [&](User *U) -> bool {
       auto *I = cast<Instruction>(U);
-      return I == Ind || !TheLoop->contains(I) || Worklist.count(I) ||
+      return I == Ind || Worklist.count(I) ||
              IsVectorizedMemAccessUse(I, IndUpdate);
     });
     if (!UniformIndUpdate)
diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
index f440bf2eb022..545d277d7aa0 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
@@ -621,28 +621,6 @@ static void legalizeAndOptimizeInductions(VPlan &Plan) {
       Def->replaceAllUsesWith(Clone);
     }

-    // Check if any uniform VPReplicateRecipes using the phi recipe are used by
-    // ExtractFromEnd. Those must be replaced by a regular VPReplicateRecipe to
-    // ensure the final value is available.
-    // TODO: Remove once uniformity analysis is done on VPlan.
-    for (VPUser *U : Users) {
-      auto *ExitIRI = dyn_cast<VPIRInstruction>(U);
-      VPValue *Op;
-      if (!ExitIRI || !match(ExitIRI->getOperand(0),
-                             m_VPInstruction<VPInstruction::ExtractFromEnd>(
-                                 m_VPValue(Op), m_VPValue())))
-        continue;
-      auto *RepR = dyn_cast<VPReplicateRecipe>(Op);
-      if (!RepR || !RepR->isUniform())
-        continue;
-      assert(!RepR->isPredicated() && "RepR must not be predicated");
-      Instruction *I = RepR->getUnderlyingInstr();
-      auto *Clone =
-          new VPReplicateRecipe(I, RepR->operands(), /*IsUniform*/ false);
-      Clone->insertAfter(RepR);
-      RepR->replaceAllUsesWith(Clone);
-    }
-
     // Replace wide pointer inductions which have only their scalars used by
     // PtrAdd(IndStart, ScalarIVSteps (0, Step)).
     if (auto *PtrIV = dyn_cast<VPWidenPointerInductionRecipe>(&Phi)) {

[clang] Miscompilation at -O2/3

This code prints 0 at `-O0/1` and triggers SIGKILL at `-O2/3`:

```c
int printf(const char *, ...);
int a;
short b, c;
long e;
int f[8][1];
unsigned g;
int h(int i) {
  long d = 0;
  for (; (a -= i) >= 0; d += 6)
    ;
  return d;
}
void j() {
  g = 0;
  for (; h(90) + g <= 0; g++) {
    int k = -1;
    b = 0;
    for (; k + g - -1 + b <= 3; b++)
      f[b + 3][0] = c;
    for (; b + g - 3 + e <= 8; e++)
      ;
    for (; e <= 3;)
      ;
  }
}
int main() {
  j();
  printf("%d\n", f[0][0]);
}
```

Compiler Explorer: https://godbolt.org/z/3x8Yc3fnW

It seems to be a recent regression.

Bisecting now

Reproducer: https://godbolt.org/z/6bzT9rs3K
```
; bin/opt -passes=loop-vectorize test.ll -S
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

@f = global [8 x [1 x i32]] zeroinitializer

define i32 @main() {
entry:
  br label %for.body6.i

for.body6.i:                                      ; preds = %for.body6.i, %entry
  %conv34.i = phi i32 [ %conv.i, %for.body6.i ], [ 0, %entry ]
  %storemerge3133.i = phi i16 [ %inc.i, %for.body6.i ], [ 0, %entry ]
  %idxprom.i = zext i32 %conv34.i to i64
  %arrayidx.i = getelementptr [8 x [1 x i32]], ptr @f, i64 0, i64 %idxprom.i
  store i32 0, ptr %arrayidx.i, align 4
  %inc.i = add i16 %storemerge3133.i, 1
  %conv.i = zext i16 %inc.i to i32
  %cmp4.i = icmp ult i16 %storemerge3133.i, 3
  br i1 %cmp4.i, label %for.body6.i, label %for.cond11thread-pre-split.i

for.cond11thread-pre-split.i:                     ; preds = %for.body6.i
  %0 = add i32 %conv.i, -9
  %cmp24.i = icmp ult i32 %0, -6
  br i1 %cmp24.i, label %for.cond23.i, label %for.end27.i

for.cond23.i:                                     ; preds = %for.cond23.i, %for.cond11thread-pre-split.i
  br label %for.cond23.i

for.end27.i:                                      ; preds = %for.cond11thread-pre-split.i
  ret i32 0
}
```
[llubi](https://github.com/dtcxzyw/llvm-ub-aware-interpreter) output:

Before:
```
Entering function main
  br label %for.body6.i jump to %for.body6.i
    phi i32 %conv34.i -> i32 0
    phi i16 %storemerge3133.i -> i16 0
  %idxprom.i = zext i32 %conv34.i to i64 -> i64 0
  %arrayidx.i = getelementptr [8 x [1 x i32]], ptr @f, i64 0, i64 %idxprom.i -> Ptr 16[@f]
  store i32 0, ptr %arrayidx.i, align 4
  %inc.i = add i16 %storemerge3133.i, 1 -> i16 1
  %conv.i = zext i16 %inc.i to i32 -> i32 1
  %cmp4.i = icmp ult i16 %storemerge3133.i, 3 -> T
  br i1 %cmp4.i, label %for.body6.i, label %for.cond11thread-pre-split.i jump to %for.body6.i
    phi i32 %conv34.i -> i32 1
    phi i16 %storemerge3133.i -> i16 1
  %idxprom.i = zext i32 %conv34.i to i64 -> i64 1
  %arrayidx.i = getelementptr [8 x [1 x i32]], ptr @f, i64 0, i64 %idxprom.i -> Ptr 20[@f + 4]
  store i32 0, ptr %arrayidx.i, align 4
  %inc.i = add i16 %storemerge3133.i, 1 -> i16 2
  %conv.i = zext i16 %inc.i to i32 -> i32 2
  %cmp4.i = icmp ult i16 %storemerge3133.i, 3 -> T
  br i1 %cmp4.i, label %for.body6.i, label %for.cond11thread-pre-split.i jump to %for.body6.i
    phi i32 %conv34.i -> i32 2
    phi i16 %storemerge3133.i -> i16 2
  %idxprom.i = zext i32 %conv34.i to i64 -> i64 2
  %arrayidx.i = getelementptr [8 x [1 x i32]], ptr @f, i64 0, i64 %idxprom.i -> Ptr 24[@f + 8]
  store i32 0, ptr %arrayidx.i, align 4
  %inc.i = add i16 %storemerge3133.i, 1 -> i16 3
  %conv.i = zext i16 %inc.i to i32 -> i32 3
  %cmp4.i = icmp ult i16 %storemerge3133.i, 3 -> T
  br i1 %cmp4.i, label %for.body6.i, label %for.cond11thread-pre-split.i jump to %for.body6.i
    phi i32 %conv34.i -> i32 3
    phi i16 %storemerge3133.i -> i16 3
  %idxprom.i = zext i32 %conv34.i to i64 -> i64 3
  %arrayidx.i = getelementptr [8 x [1 x i32]], ptr @f, i64 0, i64 %idxprom.i -> Ptr 28[@f + 12]
  store i32 0, ptr %arrayidx.i, align 4
  %inc.i = add i16 %storemerge3133.i, 1 -> i16 4
  %conv.i = zext i16 %inc.i to i32 -> i32 4
  %cmp4.i = icmp ult i16 %storemerge3133.i, 3 -> F
  br i1 %cmp4.i, label %for.body6.i, label %for.cond11thread-pre-split.i jump to %for.cond11thread-pre-split.i
  %0 = add i32 %conv.i, -9 -> i32 -5
  %cmp24.i = icmp ult i32 %0, -6 -> F
  br i1 %cmp24.i, label %for.cond23.i, label %for.end27.i jump to %for.end27.i
  ret i32 0
Exiting function main
```
After:
```
Entering function main
  br i1 false, label %scalar.ph, label %vector.ph jump to %vector.ph
  br label %vector.body jump to %vector.body
  %0 = zext i32 0 to i64 -> i64 0
  %1 = getelementptr [8 x [1 x i32]], ptr @f, i64 0, i64 %0 -> Ptr 16[@f]
  %2 = getelementptr i32, ptr %1, i32 0 -> Ptr 16[@f]
  store <4 x i32> zeroinitializer, ptr %2, align 4
  %3 = add i16 0, 1 -> i16 1
  %4 = zext i16 %3 to i32 -> i32 1
  %5 = zext i16 %3 to i32 -> i32 1
  %6 = zext i16 %3 to i32 -> i32 1
  %7 = zext i16 %3 to i32 -> i32 1
  br label %middle.block jump to %middle.block
  br i1 true, label %for.cond11thread-pre-split.i, label %scalar.ph jump to %for.cond11thread-pre-split.i
    phi i32 %conv.i.lcssa -> i32 1
  %8 = add i32 %conv.i.lcssa, -9 -> i32 -8
  %cmp24.i = icmp ult i32 %8, -6 -> T
  br i1 %cmp24.i, label %for.cond23.i.preheader, label %for.end27.i jump to %for.cond23.i.preheader
  br label %for.cond23.i jump to %for.cond23.i
  br label %for.cond23.i jump to %for.cond23.i
  br label %for.cond23.i jump to %for.cond23.i
  ...
```


commit 4b84288f00f3e112045bbc4be4f1539147574ead
Author: Florian Hahn <flo@fhahn.com>
Date:   Wed Aug 28 19:12:04 2024 +0100

    [VPlan] Pass live-ins used as exit values straight to live-out.

    Live-ins that are used as exit values don't need to be extracted, they
    can be passed through directly. This fixes a crash when trying to
    extract from a live-in.

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

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 4c68a95b9c26..cb104c4ed2d0 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -8648,6 +8648,11 @@ addUsersInExitBlock(VPlan &Plan,

   // Introduce VPUsers modeling the exit values.
   for (const auto &[ExitPhi, V] : ExitingValuesToFix) {
+    // Pass live-in values used by exit phis directly through to the live-out.
+    if (V->isLiveIn()) {
+      Plan.addLiveOut(ExitPhi, V);
+      continue;
+    }
     VPValue *Ext = B.createNaryOp(
         VPInstruction::ExtractFromEnd,
         {V, Plan.getOrAddLiveIn(ConstantInt::get(

opt -p loop-vectorize -force-vector-width=4 -S %s

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

define <2 x i64> @exit_value_vector_live_in(ptr %dst) {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next.1, %loop ]
  %gep = getelementptr i16, ptr %dst, i64 %iv
  store i16 0, ptr %gep, align 2
  %iv.next.1 = add i64 %iv, 1
  %ec = icmp ult i64 %iv, 1000
  br i1 %ec, label %loop, label %exit

exit:                                             ; preds = %loop
  %res = phi <2 x i64> [ zeroinitializer, %loop ]
  ret <2 x i64> %res
}

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

define i64 @exit_value_scalar_live_in(ptr %dst, i64 %in) {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next.1, %loop ]
  %gep = getelementptr i16, ptr %dst, i64 %iv
  store i16 0, ptr %gep, align 2
  %iv.next.1 = add i64 %iv, 1
  %ec = icmp ult i64 %iv, 1000
  br i1 %ec, label %loop, label %exit

exit:                                             ; preds = %loop
  %res = phi i64 [ %in, %loop ]
  ret i64 %res
}

[LoopVectorize] Assertion `(GeneratedValue->getType()->isVectorTy() == !GeneratesPerFirstLaneOnly || State.VF.isScalar()) && "scalar value but not only first lane defined"' failed.

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 fastcc void @g() #0 {
for.cond1.preheader.us.preheader:
  br label %for.cond.cleanup20.us.us.1

for.cond.cleanup20.us.us.1:                       ; preds = %for.cond.cleanup20.us.us.1, %for.cond1.preheader.us.preheader
  %indvars.iv.1 = phi i64 [ 0, %for.cond1.preheader.us.preheader ], [ %indvars.iv.next.1, %for.cond.cleanup20.us.us.1 ]
  %arrayidx.us.us.1 = getelementptr [0 x i16], ptr null, i64 0, i64 %indvars.iv.1
  store i16 0, ptr %arrayidx.us.us.1, align 2
  %indvars.iv.next.1 = add i64 %indvars.iv.1, 1
  %cmp12.us.us.1 = icmp ult i64 %indvars.iv.1, 1
  br i1 %cmp12.us.us.1, label %for.cond.cleanup20.us.us.1, label %for.cond.cleanup14.us.us.1

for.cond.cleanup14.us.us.1:                       ; preds = %for.cond.cleanup20.us.us.1
  %.lcssa.1 = phi <2 x i64> [ zeroinitializer, %for.cond.cleanup20.us.us.1 ]
  ret void
}

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

Command/backtrace:
```
> /scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt -passes=loop-vectorize -S reduced.ll
opt: /scratch/tc-testing/tc-compiler-fuzz-trunk/llvm/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp:732: virtual void llvm::VPInstruction::execute(llvm::VPTransformState&): Assertion `(GeneratedValue->getType()->isVectorTy() == !GeneratesPerFirstLaneOnly || State.VF.isScalar()) && "scalar value but not only first lane defined"' 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 -S reduced.ll
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 "g"
 #0 0x0000644a7eb61500 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x300e500)
 #1 0x0000644a7eb5e91f llvm::sys::RunSignalHandlers() (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x300b91f)
 #2 0x0000644a7eb5ea75 SignalHandler(int) Signals.cpp:0:0
 #3 0x0000790e6c842520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #4 0x0000790e6c8969fc __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #5 0x0000790e6c8969fc __pthread_kill_internal ./nptl/pthread_kill.c:78:10
 #6 0x0000790e6c8969fc pthread_kill ./nptl/pthread_kill.c:89:10
 #7 0x0000790e6c842476 gsignal ./signal/../sysdeps/posix/raise.c:27:6
 #8 0x0000790e6c8287f3 abort ./stdlib/abort.c:81:7
 #9 0x0000790e6c82871b _nl_load_domain ./intl/loadmsgcat.c:1177:9
#10 0x0000790e6c839e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
#11 0x0000644a7dc8e57a llvm::VPInstruction::execute(llvm::VPTransformState&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x213b57a)
#12 0x0000644a7dc4f617 llvm::VPBasicBlock::executeRecipes(llvm::VPTransformState*, llvm::BasicBlock*) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x20fc617)
#13 0x0000644a7dc4f910 llvm::VPIRBasicBlock::execute(llvm::VPTransformState*) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x20fc910)
#14 0x0000644a7dc51c2d llvm::VPlan::execute(llvm::VPTransformState*) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x20fec2d)
#15 0x0000644a7db37af9 llvm::LoopVectorizationPlanner::executePlan(llvm::ElementCount, unsigned int, llvm::VPlan&, llvm::InnerLoopVectorizer&, llvm::DominatorTree*, bool, llvm::DenseMap<llvm::SCEV const*, llvm::Value*, llvm::DenseMapInfo<llvm::SCEV const*, void>, llvm::detail::DenseMapPair<llvm::SCEV const*, llvm::Value*>> const*) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x1fe4af9)
#16 0x0000644a7db4afce llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x1ff7fce)
#17 0x0000644a7db4d101 llvm::LoopVectorizePass::runImpl(llvm::Function&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x1ffa101)
#18 0x0000644a7db4d777 llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x1ffa777)
#19 0x0000644a7c9b0a46 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+0xe5da46)
#20 0x0000644a7e96c95f 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+0x2e1995f)
#21 0x0000644a7c9b3bd6 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+0xe60bd6)
#22 0x0000644a7e96b6db llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2e186db)
#23 0x0000644a7c9afe76 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+0xe5ce76)
#24 0x0000644a7e96971d 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+0x2e1671d)
#25 0x0000644a7c1d9e36 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+0x686e36)
#26 0x0000644a7c1cbbc1 optMain (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x678bc1)
#27 0x0000790e6c829d90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#28 0x0000790e6c829e40 call_init ./csu/../csu/libc-start.c:128:20
#29 0x0000790e6c829e40 __libc_start_main ./csu/../csu/libc-start.c:379:5
#30 0x0000644a7c1c1f75 _start (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x66ef75)
zsh: IOT instruction (core dumped)  /scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt
```

Found via fuzzer


commit 252d01952c087cf0d141f7f281cf60efeb98be41
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Sun Mar 17 14:15:27 2024 +0800

    [InstCombine] Drop UB-implying attrs/metadata after speculating an instruction (#85542)

    When speculating an instruction in `InstCombinerImpl::FoldOpIntoSelect`,
    the call may result in undefined behavior. This patch drops all
    UB-implying attrs/metadata to fix this.

    Fixes #85536.

diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index edb046defbc1..5d3e41fb5f29 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -1650,6 +1650,7 @@ static Value *foldOperationIntoSelectOperand(Instruction &I, SelectInst *SI,
                                              Value *NewOp, InstCombiner &IC) {
   Instruction *Clone = I.clone();
   Clone->replaceUsesOfWith(SI, NewOp);
+  Clone->dropUBImplyingAttrsAndMetadata();
   IC.InsertNewInstBefore(Clone, SI->getIterator());
   return Clone;
 }

define i8 @test_drop_noundef(i1 %cond, i8 %val) {
entry:
  %sel = select i1 %cond, i8 -1, i8 %val
  %ret = call noundef i8 @llvm.smin.i8(i8 %sel, i8 0)
  ret i8 %ret
}

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

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

define i1 @pr85536(i32 %a) {
entry:
  %cmp1 = icmp ugt i32 %a, 30
  %shl1 = shl nsw i32 -1, %a
  %zext = zext i32 %shl1 to i64
  %shl2 = shl i64 %zext, 48
  %shr = ashr exact i64 %shl2, 48
  %sel = select i1 %cmp1, i64 -1, i64 %shr
  %smin = call noundef i64 @llvm.smin.i64(i64 %sel, i64 0)
  %masked = and i64 %smin, 65535
  %ret = icmp eq i64 %masked, 0
  ret i1 %ret
}

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

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

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.vector.reduce.add.v2i32(<2 x i32>) #0

define i32 @vec_to_scalar_select_vector(<2 x i1> %b) {
  %s = select <2 x i1> %b, <2 x i32> <i32 1, i32 2>, <2 x i32> <i32 3, i32 4>
  %c = call i32 @llvm.vector.reduce.add.v2i32(<2 x i32> %s)
  ret i32 %c
}

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

[InstCombine] Miscompile at -O1

Reduced test case: https://godbolt.org/z/z1a3665hd
```
#include <stdio.h>
#include <stdint.h>
static uint16_t
(safe_lshift_func_uint16_t_u_s)(uint16_t left, int right )
{
  return
    ((((int)right) < 0) || (((int)right) >= 32) || (left > ((65535) >> ((int)right)))) ?
    ((left)) :
    (left << ((int)right));
}
static int16_t
(safe_unary_minus_func_int16_t_s)(int16_t si )
{
  return
    -si;
}
static int32_t
(safe_lshift_func_int32_t_s_u)(int32_t left, unsigned int right )
{
  return
    ((left < 0) || (((unsigned int)right) >= 32) || (left > ((2147483647) >> ((unsigned int)right)))) ?
    ((left)) :
    (left << ((unsigned int)right));
}
long smin(long d, long p) { return d < p ? d : p; }
struct e { uint32_t f; } static g[] = {1, 36};
int64_t h, i;
uint8_t j(uint64_t m) {
  if (safe_lshift_func_uint16_t_u_s(
          smin(m, safe_unary_minus_func_int16_t_s(
                                safe_lshift_func_int32_t_s_u(1, g[1].f))),
          3))
     h = 0;
  return m;
}
int8_t k() {
  j(0);
  struct e *l[] = {&g[1], &g[1], &g[1], &g[1], &g[1],
                   &g[1], &g[1], &g[1], &g[1]};
  return i;
}
int main() {
  printf("%d\n", k());
  return 0;
}
```

```
> gcc -O0 -fsanitize=address,undefined -w test.c && ./a.out
0
> clang -O3 -w test.c && ./a.out
; no output
```

Reduced LLVM IR: https://alive2.llvm.org/ce/z/hWuhFG
```
%struct.e = type { i32 }

@g = internal global [2 x %struct.e] [%struct.e { i32 1 }, %struct.e { i32 36 }], align 4
@h = dso_local local_unnamed_addr global i64 0, align 8
@i = dso_local local_unnamed_addr global i64 0, align 8

define i8 @src() {
entry:
  %0 = load i32, ptr getelementptr inbounds ([2 x %struct.e], ptr @g, i64 0, i64 1), align 4
  %or.cond.i.i = icmp ult i32 %0, 31
  %shl.i.neg.i = shl nsw i32 -1, %0
  %.neg.i = zext i32 %shl.i.neg.i to i64
  %sext.i = shl i64 %.neg.i, 48
  %1 = ashr exact i64 %sext.i, 48
  %2 = call i64 @llvm.smin.i64(i64 %1, i64 0)
  %3 = and i64 %2, 65535
  %tobool.not9.i1 = icmp eq i64 %3, 0
  %tobool.not9.i = and i1 %or.cond.i.i, %tobool.not9.i1
  br i1 %tobool.not9.i, label %j.exit, label %if.then.i

if.then.i:
  store i64 0, ptr @h, align 8
  br label %j.exit

j.exit:
  %4 = load i64, ptr @i, align 8
  %conv = trunc i64 %4 to i8
  ret i8 %conv
}

==>

define i8 @tgt() {
  ret i8 poison
}
```

LLVM version: 74d1a40915834cbf0629f8d34a7265734d4d9073

cc @nikic

Reduced IR: https://alive2.llvm.org/ce/z/Gv9zkm
```
@g = internal global [1 x i32] [i32 1], align 4

define i32 @k() {
entry:
  %ret = load i32, ptr getelementptr inbounds ([1 x i32], ptr @g, i64 0), align 4
  ret i32 %ret
}

==>
define i32 @k() {
entry:
  ret i32 1
}
```

> @dtcxzyw That last transform is correct for GlobalOpt, alive2 does not support IPO transforms.

Oh, sorry about my mistake. I will provide a godbolt link.

The root cause: https://alive2.llvm.org/ce/z/ThJs3Y
```
define i1 @src(i32 %a) {
entry:
  %or.cond.i.i = icmp ugt i32 %a, 30
  %shl.i.neg.i = shl nsw i32 -1, %a
  %.neg.i = zext i32 %shl.i.neg.i to i64
  %sext.i = shl i64 %.neg.i, 48
  %1 = ashr exact i64 %sext.i, 48
  %conv2.i = select i1 %or.cond.i.i, i64 -1, i64 %1
  %cond.i8.i = call noundef i64 @llvm.smin.i64(i64 0, i64 %conv2.i)
  %2 = and i64 %cond.i8.i, 65535
  %tobool.not9.i = icmp eq i64 %2, 0
  ret i1 %tobool.not9.i
}

==>

define i1 @tgt(i32 %a) {
entry:
  %or.cond.i.i = icmp ult i32 %a, 31
  %shl.i.neg.i = shl nsw i32 -1, %a
  %.neg.i = zext i32 %shl.i.neg.i to i64
  %sext.i = shl i64 %.neg.i, 48
  %0 = ashr exact i64 %sext.i, 48
  %1 = call noundef i64 @llvm.smin.i64(i64 %0, i64 0)
  %2 = and i64 %1, 65535
  %tobool.not9.i1 = icmp eq i64 %2, 0
  %tobool.not9.i = and i1 %or.cond.i.i, %tobool.not9.i1
  ret i1 %tobool.not9.i
}
```

We forget to drop the `noundef` attribute for `smin` :(

Minimal reproducer: https://alive2.llvm.org/ce/z/aBubZ4
```
define i8 @src(i1 %cond, i8 %val) {
entry:
  %sel = select i1 %cond, i8 -1, i8 %val
  %ret = call noundef i8 @llvm.smin.i8(i8 %sel, i8 0)
  ret i8 %ret
}

==>

define i8 @tgt(i1 %cond, i8 %val) {
  %min = call noundef i8 @llvm.smin.i8(i8 %val, i8 0)
  %ret = select i1 %cond, i8 -1, i8 %min
  ret i8 %ret
}
```

@dtcxzyw We're probably missing a call to dropUBImplyingAttrsAndMetadata in FoldOpIntoSelect.


commit 212f344b84b400c0a9dedfa3c1ec6af9d9d30223
Author: Nikita Popov <npopov@redhat.com>
Date:   Mon Jan 27 16:24:15 2025 +0100

    [InstCombine] Handle constant expression result in tryFactorization()

    If IRBuilder folds the result to a constant expression, don't try
    to set nowrap flags on it.

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

diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index cad17c511b6d..a64c188575e6 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -732,7 +732,7 @@ static Value *tryFactorization(BinaryOperator &I, const SimplifyQuery &SQ,
   RetVal->takeName(&I);

   // Try to add no-overflow flags to the final value.
-  if (isa<OverflowingBinaryOperator>(RetVal)) {
+  if (isa<BinaryOperator>(RetVal)) {
     bool HasNSW = false;
     bool HasNUW = false;
     if (isa<OverflowingBinaryOperator>(&I)) {

define i16 @mul_add_to_mul_9(i16 %a) {
  %mul1 = mul nsw i16 %a, 16384
  %mul2 = mul nsw i16 %a, 16384
  %add = add nsw i16 %mul1, %mul2
  ret i16 %add
}

@g = external global i8

define i32 @shl_add_to_shl_constexpr() {
  %shl = shl i32 ptrtoint (ptr @g to i32), 1
  %add = add i32 %shl, %shl
  ret i32 %add
}

[clang] Crash at -O2: Assertion `isa<To>(Val) && "cast<Ty>() argument of incompatible type!"' failed.

This code crashes at `-O2`:

```c
int a, b;
void c();
int d(int e) {
  if (e)
    return 3;
  return 2;
}
int f(int e) {
  int i = d(e) + e;
  return i;
}
int j(int e) {
  static char g;
  char *h = &g;
  a = h - "";
  b = a << e;
  return f(b - 7) + 303 + b;
}
void k() {
  int l = j(4);
  c(l);
}
```

Compiler Explorer: https://godbolt.org/z/4h9PrKG8z

Crash:

```console
clang: /root/llvm-project/llvm/include/llvm/Support/Casting.h:578: decltype(auto) llvm::cast(From*) [with To = llvm::Instruction; From = llvm::Value]: Assertion `isa<To>(Val) && "cast<Ty>() argument of incompatible type!"' failed.
```

Backtrace:

```console
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/clang -gdwarf-4 -g -o /app/output.s -mllvm --x86-asm-syntax=intel -fno-verbose-asm -S --gcc-toolchain=/opt/compiler-explorer/gcc-snapshot -fcolor-diagnostics -fno-crash-diagnostics -O2 -Wextra -Wall <source>
1.	<eof> parser at end of file
2.	Optimizer
3.	Running pass "require<globals-aa>,function(invalidate<aa>),require<profile-summary>,cgscc(devirt<4>(inline,function-attrs<skip-non-recursive-function-attrs>,openmp-opt-cgscc,function<eager-inv;no-rerun>(sroa<modify-cfg>,early-cse<memssa>,speculative-execution<only-if-divergent-target>,jump-threading,correlated-propagation,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,instcombine<max-iterations=1;no-verify-fixpoint>,aggressive-instcombine,libcalls-shrinkwrap,tailcallelim,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,reassociate,constraint-elimination,loop-mssa(loop-instsimplify,loop-simplifycfg,licm<no-allowspeculation>,loop-rotate<header-duplication;no-prepare-for-lto>,licm<allowspeculation>,simple-loop-unswitch<no-nontrivial;trivial>),simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,instcombine<max-iterations=1;no-verify-fixpoint>,loop(loop-idiom,indvars,extra-simple-loop-unswitch-passes,loop-deletion,loop-unroll-full),sroa<modify-cfg>,vector-combine,mldst-motion<no-split-footer-bb>,gvn<>,sccp,bdce,instcombine<max-iterations=1;no-verify-fixpoint>,jump-threading,correlated-propagation,adce,memcpyopt,dse,move-auto-init,loop-mssa(licm<allowspeculation>),coro-elide,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,instcombine<max-iterations=1;no-verify-fixpoint>),function-attrs,function(require<should-not-run-function-passes>),coro-split,coro-annotation-elide)),function(invalidate<should-not-run-function-passes>),cgscc(devirt<4>())" on module "<source>"
4.	Running pass "cgscc(devirt<4>(inline,function-attrs<skip-non-recursive-function-attrs>,openmp-opt-cgscc,function<eager-inv;no-rerun>(sroa<modify-cfg>,early-cse<memssa>,speculative-execution<only-if-divergent-target>,jump-threading,correlated-propagation,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,instcombine<max-iterations=1;no-verify-fixpoint>,aggressive-instcombine,libcalls-shrinkwrap,tailcallelim,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,reassociate,constraint-elimination,loop-mssa(loop-instsimplify,loop-simplifycfg,licm<no-allowspeculation>,loop-rotate<header-duplication;no-prepare-for-lto>,licm<allowspeculation>,simple-loop-unswitch<no-nontrivial;trivial>),simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,instcombine<max-iterations=1;no-verify-fixpoint>,loop(loop-idiom,indvars,extra-simple-loop-unswitch-passes,loop-deletion,loop-unroll-full),sroa<modify-cfg>,vector-combine,mldst-motion<no-split-footer-bb>,gvn<>,sccp,bdce,instcombine<max-iterations=1;no-verify-fixpoint>,jump-threading,correlated-propagation,adce,memcpyopt,dse,move-auto-init,loop-mssa(licm<allowspeculation>),coro-elide,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,instcombine<max-iterations=1;no-verify-fixpoint>),function-attrs,function(require<should-not-run-function-passes>),coro-split,coro-annotation-elide))" on module "<source>"
5.	Running pass "instcombine<max-iterations=1;no-verify-fixpoint>" on function "k"
 #0 0x0000000003def1b8 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3def1b8)
 #1 0x0000000003dece74 llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3dece74)
 #2 0x0000000003d39368 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
 #3 0x0000789749042520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #4 0x00007897490969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #5 0x0000789749042476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #6 0x00007897490287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #7 0x000078974902871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
 #8 0x0000789749039e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
 #9 0x0000000000d8d74a (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0xd8d74a)
#10 0x0000000003935620 tryFactorization(llvm::BinaryOperator&, llvm::SimplifyQuery const&, llvm::IRBuilder<llvm::TargetFolder, llvm::IRBuilderCallbackInserter>&, llvm::Instruction::BinaryOps, llvm::Value*, llvm::Value*, llvm::Value*, llvm::Value*) InstructionCombining.cpp:0:0
#11 0x0000000003935ce2 llvm::InstCombinerImpl::tryFactorizationFolds(llvm::BinaryOperator&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3935ce2)
#12 0x0000000003935d67 llvm::InstCombinerImpl::foldUsingDistributiveLaws(llvm::BinaryOperator&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3935d67)
#13 0x0000000003972ab2 llvm::InstCombinerImpl::visitAdd(llvm::BinaryOperator&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3972ab2)
#14 0x00000000039586c1 llvm::InstCombinerImpl::run() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x39586c1)
#15 0x000000000395a066 combineInstructionsOverFunction(llvm::Function&, llvm::InstructionWorklist&, llvm::AAResults*, llvm::AssumptionCache&, llvm::TargetLibraryInfo&, llvm::TargetTransformInfo&, llvm::DominatorTree&, llvm::OptimizationRemarkEmitter&, llvm::BlockFrequencyInfo*, llvm::BranchProbabilityInfo*, llvm::ProfileSummaryInfo*, llvm::InstCombineOptions const&) (.isra.0) InstructionCombining.cpp:0:0
#16 0x000000000395b52c llvm::InstCombinePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x395b52c)
#17 0x0000000004094a6e llvm::detail::PassModel<llvm::Function, llvm::InstCombinePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4094a6e)
#18 0x0000000003796c50 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3796c50)
#19 0x000000000114aa4e llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x114aa4e)
#20 0x0000000002c71112 llvm::CGSCCToFunctionPassAdaptor::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x2c71112)
#21 0x000000000114aede llvm::detail::PassModel<llvm::LazyCallGraph::SCC, llvm::CGSCCToFunctionPassAdaptor, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x114aede)
#22 0x0000000002c68502 llvm::PassManager<llvm::LazyCallGraph::SCC, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x2c68502)
#23 0x000000000548dd6e llvm::detail::PassModel<llvm::LazyCallGraph::SCC, llvm::PassManager<llvm::LazyCallGraph::SCC, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x548dd6e)
#24 0x0000000002c6dbd6 llvm::DevirtSCCRepeatedPass::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x2c6dbd6)
#25 0x000000000548dd8e llvm::detail::PassModel<llvm::LazyCallGraph::SCC, llvm::DevirtSCCRepeatedPass, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x548dd8e)
#26 0x0000000002c6ba86 llvm::ModuleToPostOrderCGSCCPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x2c6ba86)
#27 0x000000000548dd4e llvm::detail::PassModel<llvm::Module, llvm::ModuleToPostOrderCGSCCPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x548dd4e)
#28 0x0000000003794f70 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3794f70)
#29 0x00000000056e3783 llvm::ModuleInlinerWrapperPass::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x56e3783)
#30 0x000000000532b69e llvm::detail::PassModel<llvm::Module, llvm::ModuleInlinerWrapperPass, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x532b69e)
#31 0x0000000003794f70 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3794f70)
#32 0x00000000040a7734 (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
#33 0x00000000040ab13e clang::emitBackendOutput(clang::CompilerInstance&, clang::CodeGenOptions&, llvm::StringRef, llvm::Module*, clang::BackendAction, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>, clang::BackendConsumer*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x40ab13e)
#34 0x000000000477edb0 clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x477edb0)
#35 0x00000000067c259c clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x67c259c)
#36 0x000000000477f1b8 clang::CodeGenAction::ExecuteAction() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x477f1b8)
#37 0x0000000004a44575 clang::FrontendAction::Execute() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4a44575)
#38 0x00000000049c72ae clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x49c72ae)
#39 0x0000000004b31ede clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4b31ede)
#40 0x0000000000cfcd0f cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0xcfcd0f)
#41 0x0000000000cf47aa ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#42 0x00000000047c5ae9 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::'lambda'()>(long) Job.cpp:0:0
#43 0x0000000003d39814 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3d39814)
#44 0x00000000047c60df clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (.part.0) Job.cpp:0:0
#45 0x0000000004788f4d clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4788f4d)
#46 0x0000000004789fce clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4789fce)
#47 0x0000000004791b05 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4791b05)
#48 0x0000000000cf9b23 clang_main(int, char**, llvm::ToolContext const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0xcf9b23)
#49 0x0000000000bc2a84 main (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0xbc2a84)
#50 0x0000789749029d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#51 0x0000789749029e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#52 0x0000000000cf4255 _start (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0xcf4255)
```

Looks like a clang-19 regression: https://godbolt.org/z/EvWdTGY6E

```llvm
; RUN: opt -passes=instcombine < %s
@g = external global i8

define i32 @test() {
  %shl = shl i32 ptrtoint (ptr @g to i32), 1
  %add1 = add i32 %shl, -1
  %add2 = add i32 %shl, 2
  %add3 = add i32 %add1, %add2
  ret i32 %add3
}
```

Further reduced:
```llvm
@g = external global i8

define i32 @test() {
  %shl = shl i32 ptrtoint (ptr @g to i32), 1
  %add = add i32 %shl, %shl
  ret i32 %add
}
```


commit f4f6566e44566f3d8cf9517767d457227125ca93
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Sun Dec 8 13:21:34 2024 +0800

    [InstCombine] Fix type mismatch in `foldICmpBinOpEqualityWithConstant` (#119068)

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

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index b694fde30927..54053c4c9e28 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -3622,7 +3622,8 @@ Instruction *InstCombinerImpl::foldICmpBinOpEqualityWithConstant(
               m_OneUse(m_c_Or(m_CombineAnd(m_Value(Sel),
                                            m_Select(m_Value(Cond), m_Value(TV),
                                                     m_Value(FV))),
-                              m_Value(Other))))) {
+                              m_Value(Other)))) &&
+        Cond->getType() == Cmp.getType()) {
       const SimplifyQuery Q = SQ.getWithInstruction(&Cmp);
       // Easy case is if eq/ne matches whether 0 is trueval/falseval.
       if (Pred == ICmpInst::ICMP_EQ

define <4 x i1> @pr119063(<4 x i32> %x, i1 %cond) {
entry:
  %sel = select i1 %cond, <4 x i32> splat (i32 1), <4 x i32> zeroinitializer
  %or = or <4 x i32> %sel, %x
  %cmp = icmp ne <4 x i32> %or, zeroinitializer
  ret <4 x i1> %cmp
}

declare void @use.i8(i8)

declare void @use.i1(i1)

define i1 @src_tv_ne_invert(i1 %c1, i8 %a, i8 %b, i8 %x, i8 %yy) {
  %not_c0 = icmp ugt i8 %a, %b
  call void @use.i1(i1 %not_c0)
  %c0 = xor i1 %not_c0, true
  %y = add nuw i8 %yy, 1
  %sel = select i1 %c0, i8 0, i8 %y
  %cc = or i1 %c0, %c1
  %sel_other = select i1 %cc, i8 %y, i8 %b
  %selx = or i8 %sel, %x
  %r = icmp ne i8 %selx, 0
  call void @use.i8(i8 %sel)
  call void @use.i8(i8 %sel_other)
  ret i1 %r
}

[InstCombine]  Assertion `S1->getType() == S2->getType() && "Cannot create binary operator with two operands of differing type!"' failed.

This code crashes at O2/3:
```c
int a, b;
static int c;
static int *d = &c;
short e;
char g;
unsigned short h;
int *i;
int j(int k) {
  if (k & a)
    return 1;
  return 0;
}
int l(int k) {
  int f = j(k);
  return f;
}
void n() { int *m[] = {0, &d}; }
void o() {
  for (; g; g++) {
    int *p = &b;
    short *q = &e;
    int r = l(*d + 5);
    *p = 0;
    *q = *i || (unsigned short)(r + 22158 + 36566 + *d - 1641080165) + h;
  }
}
```

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

Bisected to https://github.com/llvm/llvm-project/commit/4eb98384099cbd1d901d8ef6a210af95d9c36adf, which was committed by @fhahn

Crash:
```
clang: /root/llvm-project/llvm/lib/IR/Instructions.cpp:2642: static llvm::BinaryOperator* llvm::BinaryOperator::Create(llvm::Instruction::BinaryOps, llvm::Value*, llvm::Value*, const llvm::Twine&, llvm::InsertPosition): Assertion `S1->getType() == S2->getType() && "Cannot create binary operator with two operands of differing type!"' failed.
```

Backtrace:
```
Stack dump:
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/clang -gdwarf-4 -g -o /app/output.s -mllvm --x86-asm-syntax=intel -fno-verbose-asm -S --gcc-toolchain=/opt/compiler-explorer/gcc-snapshot -fcolor-diagnostics -fno-crash-diagnostics -O2 -Wall -Wextra <source>
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 "<source>"
4.	Running pass "instcombine<max-iterations=1;no-verify-fixpoint>" on function "o"
 #0 0x0000000003c05148 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3c05148)
 #1 0x0000000003c02e54 llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3c02e54)
 #2 0x0000000003b503b8 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
 #3 0x00007bfb65442520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #4 0x00007bfb654969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #5 0x00007bfb65442476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #6 0x00007bfb654287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #7 0x00007bfb6542871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
 #8 0x00007bfb65439e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
 #9 0x000000000351a1f3 (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x351a1f3)
#10 0x0000000003523d7c (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3523d7c)
#11 0x00000000037edc06 llvm::InstCombinerImpl::foldICmpBinOpEqualityWithConstant(llvm::ICmpInst&, llvm::BinaryOperator*, llvm::APInt const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x37edc06)
#12 0x0000000003810ac9 llvm::InstCombinerImpl::foldICmpInstWithConstant(llvm::ICmpInst&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3810ac9)
#13 0x0000000003819aad llvm::InstCombinerImpl::visitICmpInst(llvm::ICmpInst&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3819aad)
#14 0x0000000003775251 llvm::InstCombinerImpl::run() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3775251)
#15 0x0000000003776bc6 combineInstructionsOverFunction(llvm::Function&, llvm::InstructionWorklist&, llvm::AAResults*, llvm::AssumptionCache&, llvm::TargetLibraryInfo&, llvm::TargetTransformInfo&, llvm::DominatorTree&, llvm::OptimizationRemarkEmitter&, llvm::BlockFrequencyInfo*, llvm::BranchProbabilityInfo*, llvm::ProfileSummaryInfo*, llvm::InstCombineOptions const&) (.isra.0) InstructionCombining.cpp:0:0
#16 0x000000000377805c llvm::InstCombinePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x377805c)
#17 0x0000000003ea39ae llvm::detail::PassModel<llvm::Function, llvm::InstCombinePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3ea39ae)
#18 0x00000000035b5920 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x35b5920)
#19 0x00000000010f19ce llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x10f19ce)
#20 0x00000000035b423b llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x35b423b)
#21 0x00000000010f105e 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/clang+0x10f105e)
#22 0x00000000035b3c40 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x35b3c40)
#23 0x0000000003eb5912 (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
#24 0x0000000003eb918d clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, llvm::Module*, clang::BackendAction, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>, clang::BackendConsumer*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3eb918d)
#25 0x00000000045875de clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x45875de)
#26 0x000000000654152c clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x654152c)
#27 0x00000000045879b8 clang::CodeGenAction::ExecuteAction() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x45879b8)
#28 0x0000000004842b39 clang::FrontendAction::Execute() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4842b39)
#29 0x00000000047c27ce clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x47c27ce)
#30 0x000000000492db9e clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x492db9e)
#31 0x0000000000cb21bf cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0xcb21bf)
#32 0x0000000000ca9d5a ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#33 0x00000000045cad09 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::'lambda'()>(long) Job.cpp:0:0
#34 0x0000000003b50864 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3b50864)
#35 0x00000000045cb2ff clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (.part.0) Job.cpp:0:0
#36 0x000000000459149d clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x459149d)
#37 0x000000000459258d clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x459258d)
#38 0x0000000004599945 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4599945)
#39 0x0000000000caf003 clang_main(int, char**, llvm::ToolContext const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0xcaf003)
#40 0x0000000000b82f64 main (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0xb82f64)
#41 0x00007bfb65429d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#42 0x00007bfb65429e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#43 0x0000000000ca9805 _start (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0xca9805)
```

Reduced reproducer: https://godbolt.org/z/najxdPz5h


commit aad3a1630e385a6834f92a5f1d6045451ba21e4e
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Thu Oct 17 00:27:21 2024 +0800

    [ValueTracking] Respect `samesign` flag in `isKnownInversion` (#112390)

    In https://github.com/llvm/llvm-project/pull/93591 we introduced
    `isKnownInversion` and assumes `X` is poison implies `Y` is poison
    because they share common operands. But after introducing `samesign`
    this assumption no longer hold if `X` is an icmp has `samesign` flag.

    Alive2 link: https://alive2.llvm.org/ce/z/rj3EwQ (Please run it locally
    with this patch and https://github.com/AliveToolkit/alive2/pull/1098).

    This approach is the most conservative way in my mind to address this
    problem. If `X` has `samesign` flag, it will check if `Y` also has this
    flag and make sure constant RHS operands have the same sign.

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

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index eb8d17044a17..e9ed8b3c862b 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -8522,6 +8522,10 @@ bool llvm::isKnownInversion(const Value *X, const Value *Y) {
       !match(Y, m_c_ICmp(Pred2, m_Specific(A), m_Value(C))))
     return false;

+  // They must both have samesign flag or not.
+  if (cast<ICmpInst>(X)->hasSameSign() != cast<ICmpInst>(Y)->hasSameSign())
+    return false;
+
   if (B == C)
     return Pred1 == ICmpInst::getInversePredicate(Pred2);

@@ -8530,6 +8534,11 @@ bool llvm::isKnownInversion(const Value *X, const Value *Y) {
   if (!match(B, m_APInt(RHSC1)) || !match(C, m_APInt(RHSC2)))
     return false;

+  // Sign bits of two RHSCs should match.
+  if (cast<ICmpInst>(X)->hasSameSign() &&
+      RHSC1->isNonNegative() != RHSC2->isNonNegative())
+    return false;
+
   const auto CR1 = ConstantRange::makeExactICmpRegion(Pred1, *RHSC1);
   const auto CR2 = ConstantRange::makeExactICmpRegion(Pred2, *RHSC2);

define i1 @test_select_inverse_nonconst4(i64 %x, i64 %y, i64 %z, i1 %cond) {
  %cmp1 = icmp ult i64 %x, %y
  %cmp2 = icmp uge i64 %z, %y
  %sel = select i1 %cond, i1 %cmp1, i1 %cmp2
  ret i1 %sel
}

define i1 @test_select_inverse_samesign_both(i64 %x, i64 %y, i1 %cond) {
  %cmp1 = icmp samesign ult i64 %x, %y
  %cmp2 = icmp samesign uge i64 %x, %y
  %sel = select i1 %cond, i1 %cmp1, i1 %cmp2
  ret i1 %sel
}

define i1 @test_select_inverse_samesign_false_arm_rhsc_same_sign(i64 %x, i64 %y, i1 %cond) {
  %cmp1 = icmp ult i64 %x, 11
  %cmp2 = icmp samesign ugt i64 %x, 10
  %sel = select i1 %cond, i1 %cmp1, i1 %cmp2
  ret i1 %sel
}

define i1 @test_select_inverse_samesign_true_arm(i64 %x, i64 %y, i1 %cond) {
  %cmp1 = icmp samesign ult i64 %x, %y
  %cmp2 = icmp uge i64 %x, %y
  %sel = select i1 %cond, i1 %cmp1, i1 %cmp2
  ret i1 %sel
}

define i1 @test_select_inverse_samesign_true_arm_rhsc_same_sign(i64 %x, i64 %y, i1 %cond) {
  %cmp1 = icmp samesign ult i64 %x, 11
  %cmp2 = icmp ugt i64 %x, 10
  %sel = select i1 %cond, i1 %cmp1, i1 %cmp2
  ret i1 %sel
}

define i1 @test_select_inverse_samesign_both_rhsc_diff_sign(i64 %x, i64 %y, i1 %cond) {
  %cmp1 = icmp samesign slt i64 %x, 0
  %cmp2 = icmp samesign sgt i64 %x, -1
  %sel = select i1 %cond, i1 %cmp1, i1 %cmp2
  ret i1 %sel
}

define i1 @test_select_inverse_samesign_both_rhsc_same_sign(i64 %x, i64 %y, i1 %cond) {
  %cmp1 = icmp samesign ult i64 %x, 11
  %cmp2 = icmp samesign ugt i64 %x, 10
  %sel = select i1 %cond, i1 %cmp1, i1 %cmp2
  ret i1 %sel
}

define i1 @test_select_inverse_samesign_false_arm(i64 %x, i64 %y, i1 %cond) {
  %cmp1 = icmp ult i64 %x, %y
  %cmp2 = icmp samesign uge i64 %x, %y
  %sel = select i1 %cond, i1 %cmp1, i1 %cmp2
  ret i1 %sel
}

define i1 @sel_icmp_two_cmp(i1 %c, i32 %a1, i32 %a2, i32 %a3, i32 %a4) {
  %v1 = call i8 @llvm.ucmp.i8.i32(i32 %a1, i32 %a2)
  %v2 = call i8 @llvm.scmp.i8.i32(i32 %a3, i32 %a4)
  %sel = select i1 %c, i8 %v1, i8 %v2
  %cmp = icmp sle i8 %sel, 0
  ret i1 %cmp
}

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

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

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

[InstCombine] `samesign` flag should be dropped

Reproducer:
```
define i1 @src(i64 %x, i64 %y, i1 %cond) {
  %cmp1 = icmp ult i64 %x, %y
  %cmp2 = icmp samesign uge i64 %x, %y
  %sel = select i1 %cond, i1 %cmp1, i1 %cmp2
  ret i1 %sel
}

define i1 @tgt(i64 %x, i64 %y, i1 %cond) {
  %cmp2 = icmp samesign uge i64 %x, %y
  %sel = xor i1 %cond, %cmp2
  ret i1 %sel
}
```

> Don't we miss checking the flag in `hasPoisonGeneratingFlags`?

Yeah. I am preparing a patch.

> But adding support in `hasPoisonGeneratingFlags` doesn't address this issue :(

I assume we may need to `dropPoisonGeneratingFlags` in InstCombineCompares, where needed?