commit c136d3237a3c6230cfe1ab3f0f6790f903c54a27
Author: David Green <david.green@arm.com>
Date:   Wed Oct 9 16:20:03 2024 +0100

    [VectorCombine] Do not try to operate on OperandBundles. (#111635)

    This bails out if we see an intrinsic with an operand bundle on it, to
    make sure we don't process the bundles incorrectly.

    Fixes #110382.

diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
index a2ab5d966640..627edb680dfa 100644
--- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
+++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
@@ -1984,33 +1984,35 @@ bool VectorCombine::foldShuffleToIdentity(Instruction &I) {

     // We need each element to be the same type of value, and check that each
     // element has a single use.
-    if (all_of(drop_begin(Item), [Item](InstLane IL) {
-          Value *FrontV = Item.front().first->get();
-          if (!IL.first)
-            return true;
-          Value *V = IL.first->get();
-          if (auto *I = dyn_cast<Instruction>(V); I && !I->hasOneUse())
-            return false;
-          if (V->getValueID() != FrontV->getValueID())
-            return false;
-          if (auto *CI = dyn_cast<CmpInst>(V))
-            if (CI->getPredicate() != cast<CmpInst>(FrontV)->getPredicate())
-              return false;
-          if (auto *CI = dyn_cast<CastInst>(V))
-            if (CI->getSrcTy() != cast<CastInst>(FrontV)->getSrcTy())
-              return false;
-          if (auto *SI = dyn_cast<SelectInst>(V))
-            if (!isa<VectorType>(SI->getOperand(0)->getType()) ||
-                SI->getOperand(0)->getType() !=
-                    cast<SelectInst>(FrontV)->getOperand(0)->getType())
-              return false;
-          if (isa<CallInst>(V) && !isa<IntrinsicInst>(V))
-            return false;
-          auto *II = dyn_cast<IntrinsicInst>(V);
-          return !II || (isa<IntrinsicInst>(FrontV) &&
-                         II->getIntrinsicID() ==
-                             cast<IntrinsicInst>(FrontV)->getIntrinsicID());
-        })) {
+    auto CheckLaneIsEquivalentToFirst = [Item](InstLane IL) {
+      Value *FrontV = Item.front().first->get();
+      if (!IL.first)
+        return true;
+      Value *V = IL.first->get();
+      if (auto *I = dyn_cast<Instruction>(V); I && !I->hasOneUse())
+        return false;
+      if (V->getValueID() != FrontV->getValueID())
+        return false;
+      if (auto *CI = dyn_cast<CmpInst>(V))
+        if (CI->getPredicate() != cast<CmpInst>(FrontV)->getPredicate())
+          return false;
+      if (auto *CI = dyn_cast<CastInst>(V))
+        if (CI->getSrcTy() != cast<CastInst>(FrontV)->getSrcTy())
+          return false;
+      if (auto *SI = dyn_cast<SelectInst>(V))
+        if (!isa<VectorType>(SI->getOperand(0)->getType()) ||
+            SI->getOperand(0)->getType() !=
+                cast<SelectInst>(FrontV)->getOperand(0)->getType())
+          return false;
+      if (isa<CallInst>(V) && !isa<IntrinsicInst>(V))
+        return false;
+      auto *II = dyn_cast<IntrinsicInst>(V);
+      return !II || (isa<IntrinsicInst>(FrontV) &&
+                     II->getIntrinsicID() ==
+                         cast<IntrinsicInst>(FrontV)->getIntrinsicID() &&
+                     !II->hasOperandBundles());
+    };
+    if (all_of(drop_begin(Item), CheckLaneIsEquivalentToFirst)) {
       // Check the operator is one that we support.
       if (isa<BinaryOperator, CmpInst>(FrontU)) {
         //  We exclude div/rem in case they hit UB from poison lanes.
@@ -2038,7 +2040,8 @@ bool VectorCombine::foldShuffleToIdentity(Instruction &I) {
         Worklist.push_back(generateInstLaneVectorFromOperand(Item, 2));
         continue;
       } else if (auto *II = dyn_cast<IntrinsicInst>(FrontU);
-                 II && isTriviallyVectorizable(II->getIntrinsicID())) {
+                 II && isTriviallyVectorizable(II->getIntrinsicID()) &&
+                 !II->hasOperandBundles()) {
         for (unsigned Op = 0, E = II->getNumOperands() - 1; Op < E; Op++) {
           if (isVectorIntrinsicWithScalarOpAtArg(II->getIntrinsicID(), Op)) {
             if (!all_of(drop_begin(Item), [Item, Op](InstLane &IL) {

target triple = "aarch64"

define <4 x i32> @add_same_operands(<4 x i32> %x) {
  %shuf = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %add = add <4 x i32> %shuf, %shuf
  %revshuf = shufflevector <4 x i32> %add, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  ret <4 x i32> %revshuf
}

target triple = "aarch64"

define <4 x i32> @extrause_add_same_operands(<4 x i32> %x) {
  %shuf = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %add = add <4 x i32> %shuf, %shuf
  %revshuf = shufflevector <4 x i32> %add, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %add2 = add <4 x i32> %shuf, %revshuf
  ret <4 x i32> %add2
}

target triple = "aarch64"

define <8 x half> @callinst2(<8 x half> %a) {
  %ab = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %abt = call <4 x half> @llvm.fabs.v4f16(<4 x half> %at)
  %abb = call <4 x half> @othercall(<4 x half> %ab)
  %r = shufflevector <4 x half> %abt, <4 x half> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x half> %r
}

declare <4 x half> @othercall(<4 x half>)

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <4 x half> @llvm.fabs.v4f16(<4 x half>) #0

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

target triple = "aarch64"

define <4 x i32> @poison_intrinsic(<2 x i16> %l256) {
  %l266 = call <2 x i16> @llvm.abs.v2i16(<2 x i16> %l256, i1 false)
  %l267 = zext <2 x i16> %l266 to <2 x i32>
  %l271 = shufflevector <2 x i32> %l267, <2 x i32> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
  ret <4 x i32> %l271
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <2 x i16> @llvm.abs.v2i16(<2 x i16>, i1 immarg) #0

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

target triple = "aarch64"

define <8 x half> @splattwice(<8 x half> %a, <8 x half> %b) {
  %as = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> zeroinitializer
  %bs = shufflevector <8 x half> %b, <8 x half> poison, <4 x i32> zeroinitializer
  %ab1 = fadd <4 x half> %as, %bs
  %ab2 = fadd <4 x half> %as, %bs
  %r = shufflevector <4 x half> %ab1, <4 x half> %ab2, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x half> %r
}

target triple = "aarch64"

define <4 x float> @fadd_mismatched_types(<4 x float> %x, <4 x float> %y) {
  %shuf.x = shufflevector <4 x float> %x, <4 x float> poison, <2 x i32> <i32 0, i32 2>
  %shuf.y = shufflevector <4 x float> %y, <4 x float> poison, <2 x i32> <i32 1, i32 3>
  %fadd = fadd fast <2 x float> %shuf.x, %shuf.y
  %extshuf = shufflevector <2 x float> %fadd, <2 x float> poison, <4 x i32> <i32 0, i32 2, i32 1, i32 3>
  ret <4 x float> %extshuf
}

target triple = "aarch64"

define <8 x i8> @intrinsics_minmax(<8 x i8> %a, <8 x i8> %b) {
  %ab = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %bb = shufflevector <8 x i8> %b, <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %bt = shufflevector <8 x i8> %b, <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %abt = call <4 x i8> @llvm.smin.v4i8(<4 x i8> %at, <4 x i8> %bt)
  %abb = call <4 x i8> @llvm.smin.v4i8(<4 x i8> %ab, <4 x i8> %bb)
  %abt1 = call <4 x i8> @llvm.smax.v4i8(<4 x i8> %abt, <4 x i8> %bt)
  %abb1 = call <4 x i8> @llvm.smax.v4i8(<4 x i8> %abb, <4 x i8> %bb)
  %abt2 = call <4 x i8> @llvm.umin.v4i8(<4 x i8> %abt1, <4 x i8> %bt)
  %abb2 = call <4 x i8> @llvm.umin.v4i8(<4 x i8> %abb1, <4 x i8> %bb)
  %abt3 = call <4 x i8> @llvm.umax.v4i8(<4 x i8> %abt2, <4 x i8> %bt)
  %abb3 = call <4 x i8> @llvm.umax.v4i8(<4 x i8> %abb2, <4 x i8> %bb)
  %r = shufflevector <4 x i8> %abt3, <4 x i8> %abb3, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x i8> %r
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <4 x i8> @llvm.smax.v4i8(<4 x i8>, <4 x i8>) #0

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

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <4 x i8> @llvm.umax.v4i8(<4 x i8>, <4 x i8>) #0

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <4 x i8> @llvm.umin.v4i8(<4 x i8>, <4 x i8>) #0

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

target triple = "aarch64"

define <8 x i8> @fcmpsel(<8 x half> %a, <8 x half> %b, <8 x i8> %c, <8 x i8> %d) {
  %ab = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %bb = shufflevector <8 x half> %b, <8 x half> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %bt = shufflevector <8 x half> %b, <8 x half> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %cb = shufflevector <8 x i8> %c, <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %ct = shufflevector <8 x i8> %c, <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %db = shufflevector <8 x i8> %d, <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %dt = shufflevector <8 x i8> %d, <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %abt1 = fcmp olt <4 x half> %at, %bt
  %abb1 = fcmp olt <4 x half> %ab, %bb
  %abt = select <4 x i1> %abt1, <4 x i8> %ct, <4 x i8> %dt
  %abb = select <4 x i1> %abb1, <4 x i8> %cb, <4 x i8> %db
  %r = shufflevector <4 x i8> %abt, <4 x i8> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x i8> %r
}

target triple = "aarch64"

define <8 x i8> @inner_shuffle(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) {
  %ab = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
  %at = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
  %bb = shufflevector <8 x i8> %b, <8 x i8> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
  %bt = shufflevector <8 x i8> %b, <8 x i8> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
  %cs = shufflevector <8 x i8> %c, <8 x i8> poison, <4 x i32> zeroinitializer
  %abt = mul <4 x i8> %at, %bt
  %abb = mul <4 x i8> %ab, %bb
  %abt2 = shufflevector <4 x i8> %abt, <4 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %abb2 = shufflevector <4 x i8> %abb, <4 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %abt3 = add <4 x i8> %abt2, %cs
  %abb3 = add <4 x i8> %abb2, %cs
  %r = shufflevector <4 x i8> %abt3, <4 x i8> %abb3, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x i8> %r
}

target triple = "aarch64"

define <8 x i8> @add_different_operands(<8 x i8> %a, <8 x i8> %b) {
  %ab = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %bb = shufflevector <8 x i8> %b, <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %bt = shufflevector <8 x i8> %b, <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %abt = add <4 x i8> %at, %bt
  %abb = add <4 x i8> %ab, %bb
  %r = shufflevector <4 x i8> %abt, <4 x i8> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x i8> %r
}

target triple = "aarch64"

define <8 x i8> @extrause_add_different_operands(<8 x i8> %a, <8 x i8> %b) {
  %ab = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %bb = shufflevector <8 x i8> %b, <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %bt = shufflevector <8 x i8> %b, <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %abt = add <4 x i8> %at, %bt
  %abb = add <4 x i8> %ab, %bb
  call void @use(<4 x i8> %abb)
  %r = shufflevector <4 x i8> %abt, <4 x i8> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x i8> %r
}

declare void @use(<4 x i8>)

target triple = "aarch64"

define <8 x i32> @lrint(<8 x half> %a) {
  %ab = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %abt = call <4 x i32> @llvm.lrint.v4i32.v4f16(<4 x half> %at)
  %abb = call <4 x i32> @llvm.lrint.v4i32.v4f16(<4 x half> %ab)
  %r = shufflevector <4 x i32> %abt, <4 x i32> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x i32> %r
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <4 x i32> @llvm.lrint.v4i32.v4f16(<4 x half>) #0

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

target triple = "aarch64"

define <8 x half> @fadd(<8 x half> %a, <8 x half> %b) {
  %ab = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %bb = shufflevector <8 x half> %b, <8 x half> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %bt = shufflevector <8 x half> %b, <8 x half> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %abt = fadd <4 x half> %at, %bt
  %abb = fadd <4 x half> %ab, %bb
  %r = shufflevector <4 x half> %abt, <4 x half> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x half> %r
}

target triple = "aarch64"

define <8 x i8> @abs_different(<8 x i8> %a) {
  %ab = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %abt = call <4 x i8> @llvm.abs.v4i8(<4 x i8> %at, i1 true)
  %abb = call <4 x i8> @llvm.abs.v4i8(<4 x i8> %ab, i1 false)
  %r = shufflevector <4 x i8> %abt, <4 x i8> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x i8> %r
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <4 x i8> @llvm.abs.v4i8(<4 x i8>, i1 immarg) #0

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

target triple = "aarch64"

define <4 x i64> @single_zext(<4 x i32> %x) {
  %shuf = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %zext = zext <4 x i32> %shuf to <4 x i64>
  %revshuf = shufflevector <4 x i64> %zext, <4 x i64> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  ret <4 x i64> %revshuf
}

target triple = "aarch64"

define void @v8f64interleave(i64 %0, ptr %1, ptr %x, double %z) {
entry:
  %broadcast.splatinsert = insertelement <2 x double> poison, double %z, i64 0
  %broadcast.splat = shufflevector <2 x double> %broadcast.splatinsert, <2 x double> poison, <2 x i32> zeroinitializer
  %wide.vec = load <16 x double>, ptr %1, align 8
  %strided.vec = shufflevector <16 x double> %wide.vec, <16 x double> poison, <2 x i32> <i32 0, i32 8>
  %strided.vec27 = shufflevector <16 x double> %wide.vec, <16 x double> poison, <2 x i32> <i32 1, i32 9>
  %strided.vec28 = shufflevector <16 x double> %wide.vec, <16 x double> poison, <2 x i32> <i32 2, i32 10>
  %strided.vec29 = shufflevector <16 x double> %wide.vec, <16 x double> poison, <2 x i32> <i32 3, i32 11>
  %strided.vec30 = shufflevector <16 x double> %wide.vec, <16 x double> poison, <2 x i32> <i32 4, i32 12>
  %strided.vec31 = shufflevector <16 x double> %wide.vec, <16 x double> poison, <2 x i32> <i32 5, i32 13>
  %strided.vec32 = shufflevector <16 x double> %wide.vec, <16 x double> poison, <2 x i32> <i32 6, i32 14>
  %strided.vec33 = shufflevector <16 x double> %wide.vec, <16 x double> poison, <2 x i32> <i32 7, i32 15>
  %2 = fmul fast <2 x double> %strided.vec, %broadcast.splat
  %3 = getelementptr inbounds double, ptr %x, i64 %0
  %wide.vec34 = load <16 x double>, ptr %3, align 8
  %strided.vec35 = shufflevector <16 x double> %wide.vec34, <16 x double> poison, <2 x i32> <i32 0, i32 8>
  %strided.vec36 = shufflevector <16 x double> %wide.vec34, <16 x double> poison, <2 x i32> <i32 1, i32 9>
  %strided.vec37 = shufflevector <16 x double> %wide.vec34, <16 x double> poison, <2 x i32> <i32 2, i32 10>
  %strided.vec38 = shufflevector <16 x double> %wide.vec34, <16 x double> poison, <2 x i32> <i32 3, i32 11>
  %strided.vec39 = shufflevector <16 x double> %wide.vec34, <16 x double> poison, <2 x i32> <i32 4, i32 12>
  %strided.vec40 = shufflevector <16 x double> %wide.vec34, <16 x double> poison, <2 x i32> <i32 5, i32 13>
  %strided.vec41 = shufflevector <16 x double> %wide.vec34, <16 x double> poison, <2 x i32> <i32 6, i32 14>
  %strided.vec42 = shufflevector <16 x double> %wide.vec34, <16 x double> poison, <2 x i32> <i32 7, i32 15>
  %4 = fadd fast <2 x double> %strided.vec35, %2
  %5 = fmul fast <2 x double> %strided.vec27, %broadcast.splat
  %6 = fadd fast <2 x double> %strided.vec36, %5
  %7 = fmul fast <2 x double> %strided.vec28, %broadcast.splat
  %8 = fadd fast <2 x double> %strided.vec37, %7
  %9 = fmul fast <2 x double> %strided.vec29, %broadcast.splat
  %10 = fadd fast <2 x double> %strided.vec38, %9
  %11 = fmul fast <2 x double> %strided.vec30, %broadcast.splat
  %12 = fadd fast <2 x double> %strided.vec39, %11
  %13 = fmul fast <2 x double> %strided.vec31, %broadcast.splat
  %14 = fadd fast <2 x double> %strided.vec40, %13
  %15 = fmul fast <2 x double> %strided.vec32, %broadcast.splat
  %16 = fadd fast <2 x double> %strided.vec41, %15
  %17 = or disjoint i64 %0, 7
  %18 = fmul fast <2 x double> %strided.vec33, %broadcast.splat
  %19 = getelementptr inbounds double, ptr %x, i64 %17
  %20 = fadd fast <2 x double> %strided.vec42, %18
  %21 = getelementptr inbounds i8, ptr %19, i64 -56
  %22 = shufflevector <2 x double> %4, <2 x double> %6, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
  %23 = shufflevector <2 x double> %8, <2 x double> %10, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
  %24 = shufflevector <2 x double> %12, <2 x double> %14, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
  %25 = shufflevector <2 x double> %16, <2 x double> %20, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
  %26 = shufflevector <4 x double> %22, <4 x double> %23, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
  %27 = shufflevector <4 x double> %24, <4 x double> %25, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
  %interleaved.vec = shufflevector <8 x double> %26, <8 x double> %27, <16 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14, i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
  store <16 x double> %interleaved.vec, ptr %21, align 8
  ret void
}

target triple = "aarch64"

define <4 x i8> @singleop(<4 x i8> %a, <4 x i8> %b) {
  %a1 = shufflevector <4 x i8> %a, <4 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %b1 = shufflevector <4 x i8> %b, <4 x i8> poison, <4 x i32> zeroinitializer
  %a2 = zext <4 x i8> %a1 to <4 x i16>
  %b2 = zext <4 x i8> %b1 to <4 x i16>
  %ab = add <4 x i16> %a2, %b2
  %t = trunc <4 x i16> %ab to <4 x i8>
  %r = shufflevector <4 x i8> %t, <4 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  ret <4 x i8> %r
}

target triple = "aarch64"

define i32 @not_bitcast(<4 x i8> %x) {
  %shuf = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %bitcast = bitcast <4 x i8> %shuf to i32
  ret i32 %bitcast
}

target triple = "aarch64"

define <4 x i64> @zext_chain(<4 x i16> %x) {
  %shuf = shufflevector <4 x i16> %x, <4 x i16> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %zext = zext <4 x i16> %shuf to <4 x i32>
  %sext = sext <4 x i32> %zext to <4 x i64>
  %revshuf = shufflevector <4 x i64> %sext, <4 x i64> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  ret <4 x i64> %revshuf
}

target triple = "aarch64"

define <8 x i8> @intrinsics_different(<8 x i8> %a, <8 x i8> %b) {
  %ab = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %bb = shufflevector <8 x i8> %b, <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %bt = shufflevector <8 x i8> %b, <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %abt = call <4 x i8> @llvm.smin.v4i8(<4 x i8> %at, <4 x i8> %bt)
  %abb = call <4 x i8> @llvm.umin.v4i8(<4 x i8> %ab, <4 x i8> %bb)
  %r = shufflevector <4 x i8> %abt, <4 x i8> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x i8> %r
}

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

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <4 x i8> @llvm.umin.v4i8(<4 x i8>, <4 x i8>) #0

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

target triple = "aarch64"

define <8 x i8> @operandbundles_second(<8 x i8> %a) {
  %ab = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %abt = call <4 x i8> @llvm.abs.v4i8(<4 x i8> %at, i1 false)
  %abb = call <4 x i8> @llvm.abs.v4i8(<4 x i8> %ab, i1 false) [ "jl_roots"(ptr addrspace(10) null, ptr addrspace(10) null) ]
  %r = shufflevector <4 x i8> %abt, <4 x i8> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x i8> %r
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <4 x i8> @llvm.abs.v4i8(<4 x i8>, i1 immarg) #0

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

target triple = "aarch64"

define <4 x i64> @cast_mismatched_types(<4 x i32> %x) {
  %shuf = shufflevector <4 x i32> %x, <4 x i32> poison, <2 x i32> <i32 0, i32 2>
  %zext = zext <2 x i32> %shuf to <2 x i64>
  %extshuf = shufflevector <2 x i64> %zext, <2 x i64> poison, <4 x i32> <i32 0, i32 2, i32 1, i32 3>
  ret <4 x i64> %extshuf
}

target triple = "aarch64"

define <8 x i8> @operandbundles_first(<8 x i8> %a) {
  %ab = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %abt = call <4 x i8> @llvm.abs.v4i8(<4 x i8> %at, i1 false) [ "jl_roots"(ptr addrspace(10) null, ptr addrspace(10) null) ]
  %abb = call <4 x i8> @llvm.abs.v4i8(<4 x i8> %ab, i1 false)
  %r = shufflevector <4 x i8> %abt, <4 x i8> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x i8> %r
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <4 x i8> @llvm.abs.v4i8(<4 x i8>, i1 immarg) #0

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

target triple = "aarch64"

define <2 x float> @first_scalar_select(<2 x float> %0, <2 x float> %1, float %x) {
entry:
  %cmp.i903 = fcmp ogt float %x, 0.000000e+00
  %sel1639 = select i1 %cmp.i903, <2 x float> %0, <2 x float> %1
  %2 = fcmp ogt <2 x float> %0, zeroinitializer
  %sel48.i913 = select <2 x i1> %2, <2 x float> %0, <2 x float> %1
  %3 = shufflevector <2 x float> %sel1639, <2 x float> %sel48.i913, <2 x i32> <i32 0, i32 3>
  ret <2 x float> %3
}

target triple = "aarch64"

define <8 x half> @splat0(<8 x half> %a, <8 x half> %b) {
  %ab = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %bs = shufflevector <8 x half> %b, <8 x half> poison, <4 x i32> zeroinitializer
  %abt = fadd <4 x half> %at, %bs
  %abb = fadd <4 x half> %ab, %bs
  %r = shufflevector <4 x half> %abt, <4 x half> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x half> %r
}

target triple = "aarch64"

define <8 x half> @splatandidentity(<8 x half> %a, <8 x half> %b) {
  %ab = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %bs = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> zeroinitializer
  %abt = fadd <4 x half> %at, %bs
  %abb = fadd <4 x half> %ab, %bs
  %r = shufflevector <4 x half> %abt, <4 x half> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x half> %r
}

target triple = "aarch64"

define <8 x i8> @constantsplat(<8 x i8> %a) {
  %ab = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %abt = add <4 x i8> %at, splat (i8 10)
  %abb = add <4 x i8> %ab, splat (i8 10)
  %r = shufflevector <4 x i8> %abt, <4 x i8> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x i8> %r
}

target triple = "aarch64"

define void @bitcast_srcty_mismatch() {
entry:
  %shuffle.i.i = shufflevector <2 x i64> zeroinitializer, <2 x i64> zeroinitializer, <2 x i32> <i32 1, i32 3>
  %0 = bitcast <4 x i32> zeroinitializer to <4 x float>
  %1 = bitcast <2 x i64> %shuffle.i.i to <4 x float>
  %shufp.i196 = shufflevector <4 x float> %0, <4 x float> %1, <4 x i32> <i32 2, i32 1, i32 4, i32 7>
  store <4 x float> %shufp.i196, ptr null, align 16
  ret void
}

target triple = "aarch64"

define <4 x i64> @zext_add_chain(<4 x i32> %x) {
  %shuf = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %zext = zext <4 x i32> %shuf to <4 x i64>
  %add = add <4 x i64> %zext, %zext
  %revshuf = shufflevector <4 x i64> %add, <4 x i64> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  ret <4 x i64> %revshuf
}

target triple = "aarch64"

define <4 x i32> @add_chain(<4 x i32> %x) {
  %shuf = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %add = add <4 x i32> %shuf, %shuf
  %add2 = add <4 x i32> %add, %add
  %revshuf = shufflevector <4 x i32> %add2, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  ret <4 x i32> %revshuf
}

target triple = "aarch64"

define <8 x half> @splat2(<8 x half> %a, <8 x half> %b) {
  %ab = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %bs = shufflevector <8 x half> %b, <8 x half> poison, <4 x i32> <i32 2, i32 2, i32 2, i32 2>
  %abt = fadd <4 x half> %at, %bs
  %abb = fadd <4 x half> %ab, %bs
  %r = shufflevector <4 x half> %abt, <4 x half> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x half> %r
}

target triple = "aarch64"

define void @trunc(<8 x i64> %a, <8 x i64> %b, ptr %p) {
  %ab = shufflevector <8 x i64> %a, <8 x i64> poison, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
  %at = shufflevector <8 x i64> %a, <8 x i64> poison, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
  %abb1 = trunc <4 x i64> %ab to <4 x i32>
  %abt1 = trunc <4 x i64> %at to <4 x i32>
  %r = shufflevector <4 x i32> %abb1, <4 x i32> %abt1, <8 x i32> <i32 0, i32 4, i32 1, i32 5, i32 2, i32 6, i32 3, i32 7>
  store <8 x i32> %r, ptr %p, align 32
  ret void
}

target triple = "aarch64"

define <8 x half> @powi(<8 x half> %a) {
  %ab = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %abt = call <4 x half> @llvm.powi.v4f16.i32(<4 x half> %at, i32 10)
  %abb = call <4 x half> @llvm.powi.v4f16.i32(<4 x half> %ab, i32 10)
  %r = shufflevector <4 x half> %abt, <4 x half> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x half> %r
}

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

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

target triple = "aarch64"

define <8 x half> @callinst(<8 x half> %a) {
  %ab = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %abt = call <4 x half> @othercall(<4 x half> %at)
  %abb = call <4 x half> @llvm.fabs.v4f16(<4 x half> %ab)
  %r = shufflevector <4 x half> %abt, <4 x half> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x half> %r
}

declare <4 x half> @othercall(<4 x half>)

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <4 x half> @llvm.fabs.v4f16(<4 x half>) #0

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

target triple = "aarch64"

define <8 x half> @fma(<8 x half> %a, <8 x half> %b, <8 x half> %c) {
  %ab = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %bb = shufflevector <8 x half> %b, <8 x half> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %bt = shufflevector <8 x half> %b, <8 x half> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %cb = shufflevector <8 x half> %c, <8 x half> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %ct = shufflevector <8 x half> %c, <8 x half> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %abb = call <4 x half> @llvm.fma.v4f16(<4 x half> %ab, <4 x half> %bb, <4 x half> %cb)
  %abt = call <4 x half> @llvm.fma.v4f16(<4 x half> %at, <4 x half> %bt, <4 x half> %ct)
  %r = shufflevector <4 x half> %abt, <4 x half> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x half> %r
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <4 x half> @llvm.fma.v4f16(<4 x half>, <4 x half>, <4 x half>) #0

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

target triple = "aarch64"

define <8 x i8> @extrause_shuffle(<8 x i8> %a, <8 x i8> %b) {
  %ab = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %bb = shufflevector <8 x i8> %b, <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %bt = shufflevector <8 x i8> %b, <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  call void @use(<4 x i8> %bt)
  %abt = add <4 x i8> %at, %bt
  %abb = add <4 x i8> %ab, %bb
  %r = shufflevector <4 x i8> %abt, <4 x i8> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x i8> %r
}

declare void @use(<4 x i8>)

target triple = "aarch64"

define <8 x i8> @intrinsics_addsat(<8 x i8> %a, <8 x i8> %b) {
  %ab = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %bb = shufflevector <8 x i8> %b, <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %bt = shufflevector <8 x i8> %b, <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %abt = call <4 x i8> @llvm.sadd.sat.v4i8(<4 x i8> %at, <4 x i8> %bt)
  %abb = call <4 x i8> @llvm.sadd.sat.v4i8(<4 x i8> %ab, <4 x i8> %bb)
  %abt1 = call <4 x i8> @llvm.ssub.sat.v4i8(<4 x i8> %abt, <4 x i8> %bt)
  %abb1 = call <4 x i8> @llvm.ssub.sat.v4i8(<4 x i8> %abb, <4 x i8> %bb)
  %abt2 = call <4 x i8> @llvm.uadd.sat.v4i8(<4 x i8> %abt1, <4 x i8> %bt)
  %abb2 = call <4 x i8> @llvm.uadd.sat.v4i8(<4 x i8> %abb1, <4 x i8> %bb)
  %abt3 = call <4 x i8> @llvm.usub.sat.v4i8(<4 x i8> %abt2, <4 x i8> %bt)
  %abb3 = call <4 x i8> @llvm.usub.sat.v4i8(<4 x i8> %abb2, <4 x i8> %bb)
  %r = shufflevector <4 x i8> %abt3, <4 x i8> %abb3, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x i8> %r
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <4 x i8> @llvm.sadd.sat.v4i8(<4 x i8>, <4 x i8>) #0

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <4 x i8> @llvm.ssub.sat.v4i8(<4 x i8>, <4 x i8>) #0

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <4 x i8> @llvm.uadd.sat.v4i8(<4 x i8>, <4 x i8>) #0

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <4 x i8> @llvm.usub.sat.v4i8(<4 x i8>, <4 x i8>) #0

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

target triple = "aarch64"

define <4 x i64> @bitcast_smax_v8i32_v4i32(<4 x i64> %a, <4 x i64> %b) {
  %a.bc0 = bitcast <4 x i64> %a to <8 x i32>
  %b.bc0 = bitcast <4 x i64> %b to <8 x i32>
  %cmp = icmp slt <8 x i32> %a.bc0, %b.bc0
  %cmp.lo = shufflevector <8 x i1> %cmp, <8 x i1> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
  %cmp.hi = shufflevector <8 x i1> %cmp, <8 x i1> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
  %a.bc1 = bitcast <4 x i64> %a to <8 x i32>
  %b.bc1 = bitcast <4 x i64> %b to <8 x i32>
  %a.lo = shufflevector <8 x i32> %a.bc1, <8 x i32> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
  %b.lo = shufflevector <8 x i32> %b.bc1, <8 x i32> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
  %lo = select <4 x i1> %cmp.lo, <4 x i32> %b.lo, <4 x i32> %a.lo
  %a.bc2 = bitcast <4 x i64> %a to <8 x i32>
  %b.bc2 = bitcast <4 x i64> %b to <8 x i32>
  %a.hi = shufflevector <8 x i32> %a.bc2, <8 x i32> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
  %b.hi = shufflevector <8 x i32> %b.bc2, <8 x i32> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
  %hi = select <4 x i1> %cmp.hi, <4 x i32> %b.hi, <4 x i32> %a.hi
  %concat = shufflevector <4 x i32> %lo, <4 x i32> %hi, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
  %res = bitcast <8 x i32> %concat to <4 x i64>
  ret <4 x i64> %res
}

target triple = "aarch64"

define <8 x i8> @abs(<8 x i8> %a) {
  %ab = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %abt = call <4 x i8> @llvm.abs.v4i8(<4 x i8> %at, i1 false)
  %abb = call <4 x i8> @llvm.abs.v4i8(<4 x i8> %ab, i1 false)
  %r = shufflevector <4 x i8> %abt, <4 x i8> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x i8> %r
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <4 x i8> @llvm.abs.v4i8(<4 x i8>, i1 immarg) #0

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

target triple = "aarch64"

define void @maximal_legal_fpmath(ptr %addr1, ptr %addr2, ptr %result, float %val) {
  %splatinsert = insertelement <4 x float> poison, float %val, i64 0
  %incoming.vec = shufflevector <4 x float> %splatinsert, <4 x float> poison, <4 x i32> zeroinitializer
  %vec1 = load <16 x float>, ptr %addr1, align 4
  %strided.vec1 = shufflevector <16 x float> %vec1, <16 x float> poison, <4 x i32> <i32 0, i32 4, i32 8, i32 12>
  %strided.vec2 = shufflevector <16 x float> %vec1, <16 x float> poison, <4 x i32> <i32 1, i32 5, i32 9, i32 13>
  %strided.vec3 = shufflevector <16 x float> %vec1, <16 x float> poison, <4 x i32> <i32 2, i32 6, i32 10, i32 14>
  %strided.vec4 = shufflevector <16 x float> %vec1, <16 x float> poison, <4 x i32> <i32 3, i32 7, i32 11, i32 15>
  %vec2 = load <16 x float>, ptr %addr2, align 4
  %strided.vec6 = shufflevector <16 x float> %vec2, <16 x float> poison, <4 x i32> <i32 0, i32 4, i32 8, i32 12>
  %strided.vec7 = shufflevector <16 x float> %vec2, <16 x float> poison, <4 x i32> <i32 1, i32 5, i32 9, i32 13>
  %strided.vec8 = shufflevector <16 x float> %vec2, <16 x float> poison, <4 x i32> <i32 2, i32 6, i32 10, i32 14>
  %strided.vec9 = shufflevector <16 x float> %vec2, <16 x float> poison, <4 x i32> <i32 3, i32 7, i32 11, i32 15>
  %1 = fmul fast <4 x float> %incoming.vec, %strided.vec6
  %2 = fadd fast <4 x float> %strided.vec1, %1
  %3 = fmul contract <4 x float> %incoming.vec, %strided.vec7
  %4 = fadd fast <4 x float> %strided.vec2, %3
  %5 = fmul reassoc contract <4 x float> %incoming.vec, %strided.vec8
  %6 = fadd fast <4 x float> %strided.vec3, %5
  %7 = fmul reassoc contract <4 x float> %incoming.vec, %strided.vec9
  %8 = fadd reassoc contract <4 x float> %strided.vec4, %7
  %9 = shufflevector <4 x float> %2, <4 x float> %4, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
  %10 = shufflevector <4 x float> %6, <4 x float> %8, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
  %interleaved.vec = shufflevector <8 x float> %9, <8 x float> %10, <16 x i32> <i32 0, i32 4, i32 8, i32 12, i32 1, i32 5, i32 9, i32 13, i32 2, i32 6, i32 10, i32 14, i32 3, i32 7, i32 11, i32 15>
  store <16 x float> %interleaved.vec, ptr %result, align 4
  ret void
}

target triple = "aarch64"

define <4 x i64> @not_zext(<4 x i32> %x) {
  %zext = zext <4 x i32> %x to <4 x i64>
  %revshuf = shufflevector <4 x i64> %zext, <4 x i64> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  ret <4 x i64> %revshuf
}

target triple = "aarch64"

define <16 x i64> @operandbundles(<4 x i64> %a, <4 x i64> %b, <4 x i64> %c) {
  %call = call <4 x i64> @llvm.fshl.v4i64(<4 x i64> %a, <4 x i64> %b, <4 x i64> %c) [ "jl_roots"(ptr addrspace(10) null, ptr addrspace(10) null) ]
  %shufflevector = shufflevector <4 x i64> %call, <4 x i64> poison, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
  %shufflevector1 = shufflevector <16 x i64> %shufflevector, <16 x i64> undef, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
  ret <16 x i64> %shufflevector1
}

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

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

target triple = "aarch64"

define <8 x half> @fneg(<8 x half> %a, <8 x half> %b) {
  %ab = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %abt = fneg <4 x half> %at
  %abb = fneg <4 x half> %ab
  %r = shufflevector <4 x half> %abt, <4 x half> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x half> %r
}

target triple = "aarch64"

define <8 x half> @constantsplatf(<8 x half> %a) {
  %ab = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %at = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> <i32 7, i32 6, i32 5, i32 4>
  %abt = fadd <4 x half> %at, splat (half 0xH4900)
  %abb = fadd <4 x half> %ab, splat (half 0xH4900)
  %r = shufflevector <4 x half> %abt, <4 x half> %abb, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
  ret <8 x half> %r
}

target triple = "aarch64"

define <4 x i64> @not_zext2(<4 x i32> %x) {
  %shuf = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
  %zext = zext <4 x i32> %shuf to <4 x i64>
  ret <4 x i64> %zext
}

Assertion Failure in Vector Combine

Runnning vector-combine pass on
```llvm
source_filename = "text"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128-ni:10:11:12:13"
target triple = "x86_64-unknown-linux-gnu"

define nonnull ptr addrspace(10) @wombat() {
  %call = call <4 x i64> @llvm.fshl.v4i64(<4 x i64> zeroinitializer, <4 x i64> zeroinitializer, <4 x i64> <i64 45, i64 45, i64 45, i64 45>) [ "jl_roots"(ptr addrspace(10) null, ptr addrspace(10) null) ]
  %shufflevector = shufflevector <4 x i64> %call, <4 x i64> poison, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
  %shufflevector1 = shufflevector <16 x i64> %shufflevector, <16 x i64> undef, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
  ret ptr addrspace(10) null
}

declare <4 x i64> @llvm.fshl.v4i64(<4 x i64>, <4 x i64>, <4 x i64>)
```
produces
```
opt: /root/llvm-project/llvm/include/llvm/Support/Casting.h:578: decltype(auto) llvm::cast(From*) [with To = llvm::FixedVectorType; From = llvm::Type]: Assertion `isa<To>(Val) && "cast<Ty>() argument of incompatible type!"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/opt -o /app/output.s -S -passes=vector-combine <source>
1.	Running pass "function(vector-combine)" on module "<source>"
2.	Running pass "vector-combine" on function "wombat"
 #0 0x0000000005079b38 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x5079b38)
 #1 0x00000000050774ec SignalHandler(int) Signals.cpp:0:0
 #2 0x000074d0dce42520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x000074d0dce969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x000074d0dce42476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x000074d0dce287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x000074d0dce2871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
 #7 0x000074d0dce39e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
 #8 0x0000000004186458 (anonymous namespace)::VectorCombine::foldShuffleToIdentity(llvm::Instruction&) VectorCombine.cpp:0:0
 #9 0x0000000004190f01 (anonymous namespace)::VectorCombine::run()::'lambda'(llvm::Instruction&)::operator()(llvm::Instruction&) const (.isra.0) VectorCombine.cpp:0:0
#10 0x0000000004191c25 llvm::VectorCombinePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4191c25)
#11 0x0000000002f2defe llvm::detail::PassModel<llvm::Function, llvm::VectorCombinePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x2f2defe)
#12 0x0000000004e7c978 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4e7c978)
#13 0x0000000000e157ce llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xe157ce)
#14 0x0000000004e7b39e llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4e7b39e)
#15 0x0000000000e14f7e llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xe14f7e)
#16 0x0000000004e7add0 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4e7add0)
#17 0x0000000000904cc2 llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::ArrayRef<std::function<void (llvm::PassBuilder&)>>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x904cc2)
#18 0x00000000008f7b4c optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8f7b4c)
#19 0x000074d0dce29d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#20 0x000074d0dce29e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#21 0x00000000008ef61e _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8ef61e)
Program terminated with signal: SIGSEGV
Compiler returned: 139
```
Godbolt: https://godbolt.org/z/MGefYs3M5

> Runnning vector-combine pass on
> ```llvm
> source_filename = "text"
> target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128-ni:10:11:12:13"
> target triple = "x86_64-unknown-linux-gnu"
>
> define nonnull ptr addrspace(10) @wombat() {
>   %call = call <4 x i64> @llvm.fshl.v4i64(<4 x i64> zeroinitializer, <4 x i64> zeroinitializer, <4 x i64> <i64 45, i64 45, i64 45, i64 45>) [ "jl_roots"(ptr addrspace(10) null, ptr addrspace(10) null) ]
>   %shufflevector = shufflevector <4 x i64> %call, <4 x i64> poison, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
>   %shufflevector1 = shufflevector <16 x i64> %shufflevector, <16 x i64> undef, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
>   ret ptr addrspace(10) null
> }
>
> declare <4 x i64> @llvm.fshl.v4i64(<4 x i64>, <4 x i64>, <4 x i64>)
> ```
> produces
> ```
> opt: /root/llvm-project/llvm/include/llvm/Support/Casting.h:578: decltype(auto) llvm::cast(From*) [with To = llvm::FixedVectorType; From = llvm::Type]: Assertion `isa<To>(Val) && "cast<Ty>() argument of incompatible type!"' failed.
> PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
> Stack dump:
> 0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/opt -o /app/output.s -S -passes=vector-combine <source>
> 1.	Running pass "function(vector-combine)" on module "<source>"
> 2.	Running pass "vector-combine" on function "wombat"
>  #0 0x0000000005079b38 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x5079b38)
>  #1 0x00000000050774ec SignalHandler(int) Signals.cpp:0:0
>  #2 0x000074d0dce42520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
>  #3 0x000074d0dce969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
>  #4 0x000074d0dce42476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
>  #5 0x000074d0dce287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
>  #6 0x000074d0dce2871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
>  #7 0x000074d0dce39e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
>  #8 0x0000000004186458 (anonymous namespace)::VectorCombine::foldShuffleToIdentity(llvm::Instruction&) VectorCombine.cpp:0:0
>  #9 0x0000000004190f01 (anonymous namespace)::VectorCombine::run()::'lambda'(llvm::Instruction&)::operator()(llvm::Instruction&) const (.isra.0) VectorCombine.cpp:0:0
> #10 0x0000000004191c25 llvm::VectorCombinePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4191c25)
> #11 0x0000000002f2defe llvm::detail::PassModel<llvm::Function, llvm::VectorCombinePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x2f2defe)
> #12 0x0000000004e7c978 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4e7c978)
> #13 0x0000000000e157ce llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xe157ce)
> #14 0x0000000004e7b39e llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4e7b39e)
> #15 0x0000000000e14f7e llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xe14f7e)
> #16 0x0000000004e7add0 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4e7add0)
> #17 0x0000000000904cc2 llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::ArrayRef<std::function<void (llvm::PassBuilder&)>>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x904cc2)
> #18 0x00000000008f7b4c optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8f7b4c)
> #19 0x000074d0dce29d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
> #20 0x000074d0dce29e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
> #21 0x00000000008ef61e _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8ef61e)
> Program terminated with signal: SIGSEGV
> Compiler returned: 139
> ```
> Godbolt: https://godbolt.org/z/MGefYs3M5

Looks like foldShuffleToIdentity is attempting to fold the operand bundle on the fshl call


commit e7a4d78ad328d02bf515b2fa4af8b2c188a6a636
Author: DianQK <dianqk@dianqk.net>
Date:   Thu Dec 19 06:21:57 2024 +0800

    [SLP] Check if instructions exist after vectorization (#120434)

    Fixes #120433.

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index d967813075bb..88049897b29a 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -21148,8 +21148,11 @@ bool SLPVectorizerPass::vectorizeCmpInsts(iterator_range<ItT> CmpInsts,
     if (R.isDeleted(I))
       continue;
     for (Value *Op : I->operands())
-      if (auto *RootOp = dyn_cast<Instruction>(Op))
+      if (auto *RootOp = dyn_cast<Instruction>(Op)) {
         Changed |= vectorizeRootInstruction(nullptr, RootOp, BB, R);
+        if (R.isDeleted(I))
+          break;
+      }
   }
   // Try to vectorize operands as vector bundles.
   for (CmpInst *I : CmpInsts) {

[SLP] Assertion `detail::isPresent(Val) && "dyn_cast on a non-existent value"' failed.

This IR crashes on SLP: https://llvm.godbolt.org/z/8oar4o4d1

```llvm
define void @foo() {
bb:
  br label %bb1

bb1:                                              ; preds = %bb3, %bb
  %i = phi i32 [ %i26, %bb3 ], [ 0, %bb ]
  %i2 = phi i32 [ %i24, %bb3 ], [ 0, %bb ]
  br label %bb3

bb3:                                              ; preds = %bb1
  %i4 = zext i32 %i2 to i64
  %i5 = mul i64 %i4, 0
  %i10 = or i64 0, %i5
  %i11 = trunc i64 %i10 to i32
  %i12 = and i32 %i11, 0
  %i13 = zext i32 %i to i64
  %i14 = mul i64 %i13, 0
  %i19 = or i64 0, %i14
  %i20 = trunc i64 %i19 to i32
  %i21 = and i32 %i20, 0
  %i22 = or i32 %i12, %i21
  %i23 = icmp ult i32 %i22, 0
  %i24 = select i1 %i23, i32 0, i32 0
  %i25 = icmp ult i32 0, 0
  %i26 = select i1 %i25, i32 0, i32 0
  br label %bb1
}
```


commit 2c8836c899015cce49a399a6bc47b260a24a22e7
Author: Florian Hahn <flo@fhahn.com>
Date:   Sun Sep 29 20:31:23 2024 +0100

    [LV] Don't consider predicated insts as invariant unconditionally in CM.

    Predicated instructions cannot hoisted trivially, so don't treat them as
    uniform value in the cost model.

    This fixes a difference between legacy and VPlan-based cost model.

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

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index cb346be8ffe5..792e0e17dd87 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -6539,8 +6539,16 @@ LoopVectorizationCostModel::getInstructionCost(Instruction *I,
       Op2 = cast<SCEVConstant>(PSE.getSCEV(Op2))->getValue();
     }
     auto Op2Info = TTI.getOperandInfo(Op2);
-    if (Op2Info.Kind == TargetTransformInfo::OK_AnyValue &&
-        Legal->isInvariant(Op2))
+    auto IsInvariant = [this](Value *Op) {
+      if (!Legal->isInvariant(Op))
+        return false;
+      // Consider Op2 invariant, if it is not a predicated instruction in the
+      // loop. In that case, it is not trivially hoistable.
+      return !isa<Instruction>(Op) ||
+             !TheLoop->contains(cast<Instruction>(Op)) ||
+             !isPredicatedInst(cast<Instruction>(Op));
+    };
+    if (Op2Info.Kind == TargetTransformInfo::OK_AnyValue && IsInvariant(Op2))
       Op2Info.Kind = TargetTransformInfo::OK_UniformValue;

     SmallVector<const Value *, 4> Operands(I->operand_values());

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

define void @predicated_urem_shl_cost(ptr %A, i32 %x, i1 %c) {
entry:
  br label %loop.header

loop.header:                                      ; preds = %loop.latch, %entry
  %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop.latch ]
  %gep = getelementptr inbounds i32, ptr %A, i32 %iv
  %l = load i32, ptr %gep, align 4
  br i1 %c, label %then, label %loop.latch

then:                                             ; preds = %loop.header
  %rem = urem i32 2, %x
  %shl = shl i32 %l, %rem
  br label %loop.latch

loop.latch:                                       ; preds = %then, %loop.header
  %p = phi i32 [ 0, %loop.header ], [ %shl, %then ]
  store i32 %p, ptr %gep, align 4
  %iv.next = add i32 %iv, 1
  %ec = icmp eq i32 %iv, 0
  br i1 %ec, label %exit, label %loop.header

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

clang crashes at -O{2,3} on x86_64-linux-gnu: Assertion `(BestFactor.Width == LegacyVF.Width || planContainsAdditionalSimplifications(getPlanFor(BestFactor.Width), CostCtx, OrigLoop)) && " VPlan cost model and legacy cost model disagreed"' failed

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

Related to https://github.com/llvm/llvm-project/issues/108697, but it doesn't seem to trigger anymore with the latest build.

```
[519] % clangtk -v
clang version 20.0.0git (https://github.com/llvm/llvm-project.git 631bcbe9de13e160d427ad7452a7ef2ca67911ab)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /local/suz-local/software/local/clang-trunk/bin
Build config: +assertions
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/10
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/11
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/11
Candidate multilib: .;@m64
Selected multilib: .;@m64
[520] %
[520] % clangtk -O2 small.c
clang-20: /local/suz-local/software/clangbuild/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:7380: llvm::VectorizationFactor llvm::LoopVectorizationPlanner::computeBestVF(): Assertion `(BestFactor.Width == LegacyVF.Width || planContainsAdditionalSimplifications(getPlanFor(BestFactor.Width), CostCtx, OrigLoop)) && " VPlan cost model and legacy cost model disagreed"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.	Program arguments: /local/suz-local/software/local/clang-trunk/bin/clang-20 -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -dumpdir a- -disable-free -clear-ast-before-backend -main-file-name small.c -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/local/suz-local/software/emitesting/bugs/20240927-clangtk-m64-O3-build-064435/delta -fcoverage-compilation-dir=/local/suz-local/software/emitesting/bugs/20240927-clangtk-m64-O3-build-064435/delta -resource-dir /local/suz-local/software/local/clang-trunk/lib/clang/20 -I /usr/local/include -I /local/suz-local/software/local/include -internal-isystem /local/suz-local/software/local/clang-trunk/lib/clang/20/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -vectorize-loops -vectorize-slp -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/small-c6819e.o -x c small.c
1.	<eof> parser at end of file
2.	Optimizer
3.	Running pass "function<eager-inv>(float2int,lower-constant-intrinsics,loop(loop-rotate<header-duplication;no-prepare-for-lto>,loop-deletion),loop-distribute,inject-tli-mappings,loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>,infer-alignment,loop-load-elim,instcombine<max-iterations=1;no-verify-fixpoint>,simplifycfg<bonus-inst-threshold=1;forward-switch-cond;switch-range-to-icmp;switch-to-lookup;no-keep-loops;hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,slp-vectorizer,vector-combine,instcombine<max-iterations=1;no-verify-fixpoint>,loop-unroll<O2>,transform-warning,sroa<preserve-cfg>,infer-alignment,instcombine<max-iterations=1;no-verify-fixpoint>,loop-mssa(licm<allowspeculation>),alignment-from-assumptions,loop-sink,instsimplify,div-rem-pairs,tailcallelim,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;speculate-unpredictables>)" on module "small.c"
4.	Running pass "loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>" on function "main"
 #0 0x0000560d31f97bef llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x43b3bef)
 #1 0x0000560d31f953c4 SignalHandler(int) Signals.cpp:0:0
 #2 0x00007f3f4386e420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420)
 #3 0x00007f3f432a500b raise /build/glibc-LcI20x/glibc-2.31/signal/../sysdeps/unix/sysv/linux/raise.c:51:1
 #4 0x00007f3f43284859 abort /build/glibc-LcI20x/glibc-2.31/stdlib/abort.c:81:7
 #5 0x00007f3f43284729 get_sysdep_segment_value /build/glibc-LcI20x/glibc-2.31/intl/loadmsgcat.c:509:8
 #6 0x00007f3f43284729 _nl_load_domain /build/glibc-LcI20x/glibc-2.31/intl/loadmsgcat.c:970:34
 #7 0x00007f3f43295fd6 (/lib/x86_64-linux-gnu/libc.so.6+0x33fd6)
 #8 0x0000560d3393ac39 llvm::LoopVectorizationPlanner::computeBestVF() (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5d56c39)
 #9 0x0000560d3395443b llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5d7043b)
#10 0x0000560d33957301 llvm::LoopVectorizePass::runImpl(llvm::Function&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5d73301)
#11 0x0000560d33957973 llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5d73973)
#12 0x0000560d334c3406 llvm::detail::PassModel<llvm::Function, llvm::LoopVectorizePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x58df406)
#13 0x0000560d31924a81 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x3d40a81)
#14 0x0000560d2f43df76 llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x1859f76)
#15 0x0000560d319233ed llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x3d3f3ed)
#16 0x0000560d2f43cb56 llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x1858b56)
#17 0x0000560d31922e21 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x3d3ee21)
#18 0x0000560d322504b3 (anonymous namespace)::EmitAssemblyHelper::RunOptimizationPipeline(clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>&, std::unique_ptr<llvm::ToolOutputFile, std::default_delete<llvm::ToolOutputFile>>&, clang::BackendConsumer*) BackendUtil.cpp:0:0
#19 0x0000560d32253a88 clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, llvm::Module*, clang::BackendAction, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>, clang::BackendConsumer*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x466fa88)
#20 0x0000560d3293154c clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4d4d54c)
#21 0x0000560d347d56cc clang::ParseAST(clang::Sema&, bool, bool) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x6bf16cc)
#22 0x0000560d32931968 clang::CodeGenAction::ExecuteAction() (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4d4d968)
#23 0x0000560d32bf9249 clang::FrontendAction::Execute() (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5015249)
#24 0x0000560d32b752fe clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4f912fe)
#25 0x0000560d32ce5926 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5101926)
#26 0x0000560d2f004695 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x1420695)
#27 0x0000560d2effc1aa ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#28 0x0000560d2f000bde clang_main(int, char**, llvm::ToolContext const&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x141cbde)
#29 0x0000560d2eeed47b main (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x130947b)
#30 0x00007f3f43286083 __libc_start_main /build/glibc-LcI20x/glibc-2.31/csu/../csu/libc-start.c:342:3
#31 0x0000560d2effbc3e _start (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x1417c3e)
clangtk: error: unable to execute command: Aborted
clangtk: error: clang frontend command failed due to signal (use -v to see invocation)
clang version 20.0.0git (https://github.com/llvm/llvm-project.git 631bcbe9de13e160d427ad7452a7ef2ca67911ab)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /local/suz-local/software/local/clang-trunk/bin
Build config: +assertions
clangtk: note: diagnostic msg:
********************

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

********************
[521] %
[521] % cat small.c
int a, b, c, e, f, i, g, h, k, l, m;
unsigned d;
volatile int j;
int n(short o) { return o ? a % o : 0; }
int main() {
  short q;
  if (h)
    while (1)
      ;
r:
  e && j;
  if (a && j)
    goto r;
s:
  while (g)
    if (l)
      goto s;
  for (; i; i++) {
    f = !d ? : 2 % d;
    q = f > 1 ? 0 : c << f;
    m = q;
    b = n(k ^ q);
  }
  return 0;
}
```

This looks like a regression in trunk: https://godbolt.org/z/c5Wxf5Teh

I know godbolt does not have clang assertions build beyond trunk but you can use clang++ and just use `-x c` to check out if the assert exists in previous versions.

CC @fhahn

> I know godbolt does not have clang assertions build beyond trunk but you can use clang++ and just use `-x c` to check out if the assert exists in previous versions.

@shafik: Thanks for the tip!


commit ebab105670a409e426ddcb0278578711a622b1b2
Author: Nikita Popov <npopov@redhat.com>
Date:   Thu Jul 4 09:43:16 2024 +0200

    [IR] Don't strip through pointer to vector of pointer bitcasts

    When using stripPointerCasts() and getUnderlyingObject(), don't
    strip through a bitcast from ptr to <1 x ptr>, which is not a
    no-op pointer cast. Calling code is generally not prepared to
    handle that situation, resulting in incorrect alias analysis
    results for example.

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

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 5476dc5d8518..258576f0cdff 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -6403,9 +6403,10 @@ const Value *llvm::getUnderlyingObject(const Value *V, unsigned MaxLookup) {
       V = GEP->getPointerOperand();
     } else if (Operator::getOpcode(V) == Instruction::BitCast ||
                Operator::getOpcode(V) == Instruction::AddrSpaceCast) {
-      V = cast<Operator>(V)->getOperand(0);
-      if (!V->getType()->isPointerTy())
+      Value *NewV = cast<Operator>(V)->getOperand(0);
+      if (!NewV->getType()->isPointerTy())
         return V;
+      V = NewV;
     } else if (auto *GA = dyn_cast<GlobalAlias>(V)) {
       if (GA->isInterposable())
         return V;
diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp
index 8522747ccf12..b2ee75811fbb 100644
--- a/llvm/lib/IR/Value.cpp
+++ b/llvm/lib/IR/Value.cpp
@@ -652,9 +652,10 @@ static const Value *stripPointerCastsAndOffsets(
       }
       V = GEP->getPointerOperand();
     } else if (Operator::getOpcode(V) == Instruction::BitCast) {
-      V = cast<Operator>(V)->getOperand(0);
-      if (!V->getType()->isPointerTy())
+      Value *NewV = cast<Operator>(V)->getOperand(0);
+      if (!NewV->getType()->isPointerTy())
         return V;
+      V = NewV;
     } else if (StripKind != PSK_ZeroIndicesSameRepresentation &&
                Operator::getOpcode(V) == Instruction::AddrSpaceCast) {
       // TODO: If we know an address space cast will not change the

@c = dso_local global i32 0, align 4
@d = dso_local local_unnamed_addr global ptr @c, align 8

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

for.cond:                                         ; preds = %f.exit.split, %entry
  %b.0 = phi i32 [ 0, %entry ], [ %inc6, %f.exit.split ]
  %cmp = icmp ult i32 %b.0, 2
  br i1 %cmp, label %for.cond1.preheader, label %for.cond.cleanup

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

for.cond.cleanup:                                 ; preds = %for.cond
  %0 = load i32, ptr @c, align 4, !tbaa !13
  %retval = xor i32 %0, 7
  ret i32 %retval

for.cond1:                                        ; preds = %for.cond1, %for.cond1.preheader
  %i.0 = phi i32 [ %inc, %for.cond1 ], [ 0, %for.cond1.preheader ]
  %cmp2 = icmp ult i32 %i.0, 2
  %inc = add nuw nsw i32 %i.0, 1
  br i1 %cmp2, label %for.cond1, label %for.body.i.preheader, !llvm.loop !17

for.body.i.preheader:                             ; preds = %for.cond1
  %cmp2.lcssa = phi i1 [ %cmp2, %for.cond1 ]
  %1 = xor i1 %cmp2.lcssa, true
  %2 = bitcast i1 %1 to <1 x i1>
  %3 = call <1 x ptr> @llvm.masked.load.v1p0.p0(ptr @d, i32 8, <1 x i1> %2, <1 x ptr> poison), !tbaa !9
  %4 = bitcast <1 x ptr> %3 to ptr
  store i32 0, ptr @c, align 4, !tbaa !13
  %5 = load i32, ptr %4, align 4, !tbaa !13
  %tobool1.not.i = icmp ne i32 %5, 0
  %tobool1.not.i.fr = freeze i1 %tobool1.not.i
  br i1 %tobool1.not.i.fr, label %f.exit.split, label %for.body.i.preheader.split

for.body.i.preheader.split:                       ; preds = %for.body.i.preheader
  br label %for.body.i

for.body.i:                                       ; preds = %for.body.i.preheader.split, %for.body.i
  %n.04.i = phi i8 [ %add.i, %for.body.i ], [ -66, %for.body.i.preheader.split ]
  %add.i = add nsw i8 %n.04.i, 1
  %tobool.not.i = icmp eq i8 %add.i, 0
  br i1 %tobool.not.i, label %f.exit, label %for.body.i, !llvm.loop !15

f.exit:                                           ; preds = %for.body.i
  br label %f.exit.split

f.exit.split:                                     ; preds = %for.body.i.preheader, %f.exit
  store i32 7, ptr %4, align 4, !tbaa !13
  %inc6 = add nuw nsw i32 %b.0, 1
  br label %for.cond, !llvm.loop !18
}

!9 = !{!10, !10, i64 0}
!10 = !{!"any pointer", !11, i64 0}
!11 = !{!"omnipotent char", !12, i64 0}
!12 = !{!"Simple C/C++ TBAA"}
!13 = !{!14, !14, i64 0}
!14 = !{!"int", !11, i64 0}
!15 = distinct !{!15, !16}
!16 = !{!"llvm.loop.mustprogress"}
!17 = distinct !{!17, !16}
!18 = distinct !{!18, !16}

[LICM] Miscompilation caused by wrong AA result

Reproducer: https://godbolt.org/z/Y1vvbndf8
```
@c = dso_local global i32 0, align 4
@d = dso_local local_unnamed_addr global ptr @c, align 8

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

for.cond:                                         ; preds = %f.exit.split, %entry
  %b.0 = phi i32 [ 0, %entry ], [ %inc6, %f.exit.split ]
  %cmp = icmp ult i32 %b.0, 2
  br i1 %cmp, label %for.cond1.preheader, label %for.cond.cleanup

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

for.cond.cleanup:                                 ; preds = %for.cond
  %0 = load i32, ptr @c, align 4, !tbaa !13
  ret i32 %0

for.cond1:                                        ; preds = %for.cond1, %for.cond1.preheader
  %i.0 = phi i32 [ %inc, %for.cond1 ], [ 0, %for.cond1.preheader ]
  %cmp2 = icmp ult i32 %i.0, 2
  %inc = add nuw nsw i32 %i.0, 1
  br i1 %cmp2, label %for.cond1, label %for.body.i.preheader, !llvm.loop !17

for.body.i.preheader:                             ; preds = %for.cond1
  %cmp2.lcssa = phi i1 [ %cmp2, %for.cond1 ]
  %1 = xor i1 %cmp2.lcssa, true
  %2 = bitcast i1 %1 to <1 x i1>
  %3 = call <1 x ptr> @llvm.masked.load.v1p0.p0(ptr @d, i32 8, <1 x i1> %2, <1 x ptr> poison), !tbaa !9
  %4 = bitcast <1 x ptr> %3 to ptr
  store i32 0, ptr @c, align 4, !tbaa !13
  %5 = load i32, ptr %4, align 4, !tbaa !13
  %tobool1.not.i = icmp ne i32 %5, 0
  %tobool1.not.i.fr = freeze i1 %tobool1.not.i
  br i1 %tobool1.not.i.fr, label %f.exit.split, label %for.body.i.preheader.split

for.body.i.preheader.split:                       ; preds = %for.body.i.preheader
  br label %for.body.i

for.body.i:                                       ; preds = %for.body.i.preheader.split, %for.body.i
  %n.04.i = phi i8 [ %add.i, %for.body.i ], [ -66, %for.body.i.preheader.split ]
  %add.i = add nsw i8 %n.04.i, 1
  %tobool.not.i = icmp eq i8 %add.i, 0
  br i1 %tobool.not.i, label %f.exit, label %for.body.i, !llvm.loop !15

f.exit:                                           ; preds = %for.body.i
  br label %f.exit.split

f.exit.split:                                     ; preds = %for.body.i.preheader, %f.exit
  store i32 7, ptr %4, align 4, !tbaa !13
  %inc6 = add nuw nsw i32 %b.0, 1
  br label %for.cond, !llvm.loop !18
}

!9 = !{!10, !10, i64 0}
!10 = !{!"any pointer", !11, i64 0}
!11 = !{!"omnipotent char", !12, i64 0}
!12 = !{!"Simple C/C++ TBAA"}
!13 = !{!14, !14, i64 0}
!14 = !{!"int", !11, i64 0}
!15 = distinct !{!15, !16}
!16 = !{!"llvm.loop.mustprogress"}
!17 = distinct !{!17, !16}
!18 = distinct !{!18, !16}
```
After LICM:
```
source_filename = "/app/example.ll"

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

for.cond:                                         ; preds = %f.exit.split, %entry
  %0 = phi i32 [ poison, %entry ], [ 0, %f.exit.split ]
  %b.0 = phi i32 [ 0, %entry ], [ %inc6, %f.exit.split ]
  %cmp = icmp ult i32 %b.0, 2
  br i1 %cmp, label %for.cond1.preheader, label %for.cond.cleanup

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

for.cond.cleanup:                                 ; preds = %for.cond
  %.lcssa = phi i32 [ %0, %for.cond ]
  store i32 %.lcssa, ptr @c, align 4, !tbaa !0
  %1 = load i32, ptr @c, align 4, !tbaa !0
  ret i32 %1

for.cond1:                                        ; preds = %for.cond1, %for.cond1.preheader
  %i.0 = phi i32 [ %inc, %for.cond1 ], [ 0, %for.cond1.preheader ]
  %cmp2 = icmp ult i32 %i.0, 2
  %inc = add nuw nsw i32 %i.0, 1
  br i1 %cmp2, label %for.cond1, label %for.body.i.preheader, !llvm.loop !4

for.body.i.preheader:                             ; preds = %for.cond1
  %cmp2.lcssa = phi i1 [ %cmp2, %for.cond1 ]
  %2 = xor i1 %cmp2.lcssa, true
  %3 = bitcast i1 %2 to <1 x i1>
  %4 = call <1 x ptr> @llvm.masked.load.v1p0.p0(ptr @d, i32 8, <1 x i1> %3, <1 x ptr> poison), !tbaa !6
  %5 = bitcast <1 x ptr> %4 to ptr
  %6 = load i32, ptr %5, align 4, !tbaa !0
  %tobool1.not.i = icmp ne i32 %6, 0
  %tobool1.not.i.fr = freeze i1 %tobool1.not.i
  br i1 %tobool1.not.i.fr, label %f.exit.split, label %for.body.i.preheader.split

for.body.i.preheader.split:                       ; preds = %for.body.i.preheader
  br label %for.body.i

for.body.i:                                       ; preds = %for.body.i, %for.body.i.preheader.split
  %n.04.i = phi i8 [ %add.i, %for.body.i ], [ -66, %for.body.i.preheader.split ]
  %add.i = add nsw i8 %n.04.i, 1
  %tobool.not.i = icmp eq i8 %add.i, 0
  br i1 %tobool.not.i, label %f.exit, label %for.body.i, !llvm.loop !8

f.exit:                                           ; preds = %for.body.i
  br label %f.exit.split

f.exit.split:                                     ; preds = %f.exit, %for.body.i.preheader
  store i32 7, ptr %5, align 4, !tbaa !0
  %inc6 = add nuw nsw i32 %b.0, 1
  br label %for.cond, !llvm.loop !9
}

declare <1 x ptr> @llvm.masked.load.v1p0.p0(ptr nocapture, i32 immarg, <1 x i1>, <1 x ptr>) #0

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

!0 = !{!1, !1, i64 0}
!1 = !{!"int", !2, i64 0}
!2 = !{!"omnipotent char", !3, i64 0}
!3 = !{!"Simple C/C++ TBAA"}
!4 = distinct !{!4, !5}
!5 = !{!"llvm.loop.mustprogress"}
!6 = !{!7, !7, i64 0}
!7 = !{!"any pointer", !2, i64 0}
!8 = distinct !{!8, !5}
!9 = distinct !{!9, !5}
```
```
> lli test.ll
> echo $?
7
> bin/opt -passes=licm test.ll -S -o out.ll
> lli out.ll
> echo $?
0
```
`store i32 7, ptr %5, align 4, !tbaa !0` may write something to `@c`. So this transform is incorrect.

Related patch: https://github.com/llvm/llvm-project/pull/96878
Original C code (needs x86 +cf or riscv +zicldst):
```
#include "csmith.h"
uint32_t c = 0;
int32_t *d = &c;
void f(int32_t *o) {
  uint8_t n;
  for (n = 190; n; n += 1) {
    *o = 0;
    if (*d)
      break;
  }
}
int main() {
  for (int b = 0; b <= 1; b++) {
    uint64_t j[2];
    int i;
    for (i = 0; i < 2; i++)
      j[i] = 1;
    f(&c);
    safe_add_func_int32_t_s_s(0, j[1]);
    *d = 7;
  }
  printf("%d\n", c);
  return 0;
}
```

cc @nikic @fhahn @KanRobert

miscompilation TBAA llvm:ir llvm:analysis

Hm, we probably have a lot of places that don't handle things like `bitcast <1 x ptr> %3 to ptr` correctly, and assume that bitcast of pointer is always a pointer to pointer cast.

> Which patch supports `zicldst` for riscv? @dtcxzyw

We have a prototype which is still working in progress:
+ llvm support: https://github.com/llvm/llvm-project/compare/main...dtcxzyw:llvm-project:zicldst-support
+ qemu support: https://github.com/qemu/qemu/compare/master...cyyself:qemu:exp_rv_zicldst


commit 5b342e6041f8567a39354ae3c5346cf74b3bb84f
Author: Stephen Tozer <stephen.tozer@sony.com>
Date:   Mon Feb 19 11:38:04 2024 +0000

    [RemoveDIs][DebugInfo] Check for null marker when printing DPValues (#82238)

    The function to print DPValues currently tries to incorporate the
    function it is part of, which is found through its marker; this means
    when we try to print a DPValue with no marker, we dereference a nullptr.
    We can print instructions without parents, and so the same should be
    true for DPValues; this patch changes DPValue::print to check for a null
    marker and avoid dereferencing it.

    Fixes issue: https://github.com/llvm/llvm-project/issues/82230

diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 0ae720e8b7ce..d3c64a57f7fd 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -293,7 +293,7 @@ static const Module *getModuleFromDPI(const DPMarker *Marker) {
 }

 static const Module *getModuleFromDPI(const DPValue *DPV) {
-  return getModuleFromDPI(DPV->getMarker());
+  return DPV->getMarker() ? getModuleFromDPI(DPV->getMarker()) : nullptr;
 }

 static void PrintCallingConv(unsigned cc, raw_ostream &Out) {
@@ -4886,8 +4886,9 @@ void DPValue::print(raw_ostream &ROS, ModuleSlotTracker &MST,
     if (F)
       MST.incorporateFunction(*F);
   };
-  incorporateFunction(Marker->getParent() ? Marker->getParent()->getParent()
-                                          : nullptr);
+  incorporateFunction(Marker && Marker->getParent()
+                          ? Marker->getParent()->getParent()
+                          : nullptr);
   AssemblyWriter W(OS, SlotTable, getModuleFromDPI(this), nullptr, IsForDebug);
   W.printDPValue(*this);
 }

opt -passes="instcombine" -debug %s -o /dev/null 2>&1

;; Tests that we can debug-print DPValues that have no markers attached.
; REQUIRES: asserts

define ptr @func_10(i32 %p_11) {
entry:
  %conv108 = zext i32 %p_11 to i64
  tail call void @llvm.dbg.value(metadata i64 %conv108, metadata !4, metadata !DIExpression()), !dbg !12
  br label %func_29.exit

func_29.exit:                                     ; preds = %entry
  store i64 %conv108, ptr null, align 1
  ret ptr null
}

declare void @llvm.dbg.value(metadata, metadata, metadata)

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

!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !2, globals: !2, splitDebugInlining: false, nameTableKind: None)
!1 = !DIFile(filename: "csmith5961503756960.c", directory: "/llvm")
!2 = !{}
!3 = !{i32 2, !"Debug Info Version", i32 3}
!4 = !DILocalVariable(name: "p_31", arg: 2, scope: !5, file: !1, line: 148, type: !7)
!5 = distinct !DISubprogram(name: "func_29", scope: !1, file: !1, line: 148, type: !6, scopeLine: 149, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
!6 = !DISubroutineType(types: !2)
!7 = !DIDerivedType(tag: DW_TAG_typedef, name: "uint64_t", file: !8, line: 60, baseType: !9)
!8 = !DIFile(filename: "/foo/_stdint.h", directory: "")
!9 = !DIDerivedType(tag: DW_TAG_typedef, name: "__uint64_t", file: !10, line: 108, baseType: !11)
!10 = !DIFile(filename: "/foo/_default_types.h", directory: "")
!11 = !DIBasicType(name: "unsigned long long", size: 64, encoding: DW_ATE_unsigned)
!12 = !DILocation(line: 0, scope: !5)

opt -passes="instcombine" -debug crashes with non-instrinsic debug-info

llvm commit: d61864f813e3
Reproduce with:
```
opt -passes="instcombine" -debug bbi-92509.ll -o /dev/null
```
[bbi-92509.ll.gz](https://github.com/llvm/llvm-project/files/14329283/bbi-92509.ll.gz)

Result:
```
INSTCOMBINE ITERATION #1 on func_10
ADD:   ret ptr null
ADD:   store i64 %conv108, ptr null, align 1
ADD:   br label %func_29.exit
ADD:   %conv108 = zext i32 %p_11 to i64
CLONE: PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: ../../main-github/llvm/build-all/bin/opt -passes=instcombine -debug bbi-92509.ll -o /dev/null
 #0 0x000055e12968f4a7 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (../../main-github/llvm/build-all/bin/opt+0x3db14a7)
 #1 0x000055e12968cf7e llvm::sys::RunSignalHandlers() (../../main-github/llvm/build-all/bin/opt+0x3daef7e)
 #2 0x000055e12968fe6f SignalHandler(int) Signals.cpp:0:0
 #3 0x00007fdf33999630 __restore_rt sigaction.c:0:0
 #4 0x000055e12971f8e0 llvm::DPMarker::getParent() const (../../main-github/llvm/build-all/bin/opt+0x3e418e0)
 #5 0x000055e129761abf llvm::DPValue::print(llvm::raw_ostream&, bool) const (../../main-github/llvm/build-all/bin/opt+0x3e83abf)
 #6 0x000055e12a244957 llvm::InstCombinerImpl::tryToSinkInstructionDPValues(llvm::Instruction*, llvm::ilist_iterator_w_bits<llvm::ilist_detail::node_options<llvm::Instruction, true, false, void, true>, false, false>, llvm::BasicBlock*, llvm::BasicBlock*, llvm::SmallVectorImpl<llvm::DPValue*>&) InstructionCombining.cpp:0:0
 #7 0x000055e12a242b0c llvm::InstCombinerImpl::tryToSinkInstruction(llvm::Instruction*, llvm::BasicBlock*) InstructionCombining.cpp:0:0
 #8 0x000055e12a2453fc llvm::InstCombinerImpl::run() InstructionCombining.cpp:0:0
 #9 0x000055e12a248c79 combineInstructionsOverFunction(llvm::Function&, llvm::InstructionWorklist&, llvm::AAResults*, llvm::AssumptionCache&, llvm::TargetLibraryInfo&, llvm::TargetTransformInfo&, llvm::DominatorTree&, llvm::OptimizationRemarkEmitter&, llvm::BlockFrequencyInfo*, llvm::ProfileSummaryInfo*, llvm::LoopInfo*, llvm::InstCombineOptions const&) InstructionCombining.cpp:0:0
#10 0x000055e12a2482ea llvm::InstCombinePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (../../main-github/llvm/build-all/bin/opt+0x496a2ea)
#11 0x000055e12a95e5bd llvm::detail::PassModel<llvm::Function, llvm::InstCombinePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) PassBuilderPipelines.cpp:0:0
#12 0x000055e12989a8e4 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (../../main-github/llvm/build-all/bin/opt+0x3fbc8e4)
#13 0x000055e12a9644dd llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) PassBuilderPipelines.cpp:0:0
#14 0x000055e12989f9ae llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (../../main-github/llvm/build-all/bin/opt+0x3fc19ae)
#15 0x000055e12a95dd9d llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) PassBuilderPipelines.cpp:0:0
#16 0x000055e129899456 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (../../main-github/llvm/build-all/bin/opt+0x3fbb456)
#17 0x000055e12a90a42b 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) (../../main-github/llvm/build-all/bin/opt+0x502c42b)
#18 0x000055e129657a28 optMain (../../main-github/llvm/build-all/bin/opt+0x3d79a28)
#19 0x00007fdf310cc555 __libc_start_main (/lib64/libc.so.6+0x22555)
#20 0x000055e129651369 _start (../../main-github/llvm/build-all/bin/opt+0x3d73369)
Segmentation fault (core dumped)
```

This starts happening with a93a4ec7dd205
```
Reapply "[DebugInfo][RemoveDIs] Turn on non-instrinsic debug-info by default"
```

> Should be fixed by: [5b342e6](https://github.com/llvm/llvm-project/commit/5b342e6041f8567a39354ae3c5346cf74b3bb84f)

Yep, thanks!


GVNPass::performScalarPRE GVNPass::processAssumeIntrinsic GVNPass::processInstruction patchAndReplaceAllUsesWith

commit f16bff1261a92169992c6edf6bc6b38d1c815c8d
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Fri Nov 1 12:44:33 2024 +0800

    [GVN][NewGVN][Local] Handle attributes for function calls after CSE (#114011)

    This patch intersects attributes of two calls to avoid introducing UB.
    It also skips incompatible call pairs in GVN/NewGVN. However, I cannot
    provide negative tests for these changes.

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

diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp
index 2ba600497e00..ad9b1217089d 100644
--- a/llvm/lib/Transforms/Scalar/GVN.cpp
+++ b/llvm/lib/Transforms/Scalar/GVN.cpp
@@ -2189,6 +2189,16 @@ bool GVNPass::processAssumeIntrinsic(AssumeInst *IntrinsicI) {
   return Changed;
 }

+// Return true iff V1 can be replaced with V2.
+static bool canBeReplacedBy(Value *V1, Value *V2) {
+  if (auto *CB1 = dyn_cast<CallBase>(V1))
+    if (auto *CB2 = dyn_cast<CallBase>(V2))
+      return CB1->getAttributes()
+          .intersectWith(CB2->getContext(), CB2->getAttributes())
+          .has_value();
+  return true;
+}
+
 static void patchAndReplaceAllUsesWith(Instruction *I, Value *Repl) {
   patchReplacementInstruction(I, Repl);
   I->replaceAllUsesWith(Repl);
@@ -2734,7 +2744,7 @@ bool GVNPass::processInstruction(Instruction *I) {
   // Perform fast-path value-number based elimination of values inherited from
   // dominators.
   Value *Repl = findLeader(I->getParent(), Num);
-  if (!Repl) {
+  if (!Repl || !canBeReplacedBy(I, Repl)) {
     // Failure, just remember this instance for future use.
     LeaderTable.insert(Num, I, I->getParent());
     return false;
@@ -3000,7 +3010,7 @@ bool GVNPass::performScalarPRE(Instruction *CurInst) {

     uint32_t TValNo = VN.phiTranslate(P, CurrentBlock, ValNo, *this);
     Value *predV = findLeader(P, TValNo);
-    if (!predV) {
+    if (!predV || !canBeReplacedBy(CurInst, predV)) {
       predMap.push_back(std::make_pair(static_cast<Value *>(nullptr), P));
       PREPred = P;
       ++NumWithout;
diff --git a/llvm/lib/Transforms/Scalar/NewGVN.cpp b/llvm/lib/Transforms/Scalar/NewGVN.cpp
index 13d9e8f186b4..6800ad51cc0a 100644
--- a/llvm/lib/Transforms/Scalar/NewGVN.cpp
+++ b/llvm/lib/Transforms/Scalar/NewGVN.cpp
@@ -3854,6 +3854,16 @@ Value *NewGVN::findPHIOfOpsLeader(const Expression *E,
   return nullptr;
 }

+// Return true iff V1 can be replaced with V2.
+static bool canBeReplacedBy(Value *V1, Value *V2) {
+  if (auto *CB1 = dyn_cast<CallBase>(V1))
+    if (auto *CB2 = dyn_cast<CallBase>(V2))
+      return CB1->getAttributes()
+          .intersectWith(CB2->getContext(), CB2->getAttributes())
+          .has_value();
+  return true;
+}
+
 bool NewGVN::eliminateInstructions(Function &F) {
   // This is a non-standard eliminator. The normal way to eliminate is
   // to walk the dominator tree in order, keeping track of available
@@ -3963,6 +3973,9 @@ bool NewGVN::eliminateInstructions(Function &F) {
           MembersLeft.insert(Member);
           continue;
         }
+        if (!canBeReplacedBy(Member, Leader))
+          continue;
+
         LLVM_DEBUG(dbgs() << "Found replacement " << *(Leader) << " for "
                           << *Member << "\n");
         auto *I = cast<Instruction>(Member);
@@ -4069,8 +4082,11 @@ bool NewGVN::eliminateInstructions(Function &F) {
               if (DominatingLeader != Def) {
                 // Even if the instruction is removed, we still need to update
                 // flags/metadata due to downstreams users of the leader.
-                if (!match(DefI, m_Intrinsic<Intrinsic::ssa_copy>()))
+                if (!match(DefI, m_Intrinsic<Intrinsic::ssa_copy>())) {
+                  if (!canBeReplacedBy(DefI, DominatingLeader))
+                    continue;
                   patchReplacementInstruction(DefI, DominatingLeader);
+                }

                 markInstructionForDeletion(DefI);
               }
@@ -4112,17 +4128,21 @@ bool NewGVN::eliminateInstructions(Function &F) {
           // Don't replace our existing users with ourselves.
           if (U->get() == DominatingLeader)
             continue;
-          LLVM_DEBUG(dbgs()
-                     << "Found replacement " << *DominatingLeader << " for "
-                     << *U->get() << " in " << *(U->getUser()) << "\n");

           // If we replaced something in an instruction, handle the patching of
           // metadata.  Skip this if we are replacing predicateinfo with its
           // original operand, as we already know we can just drop it.
           auto *ReplacedInst = cast<Instruction>(U->get());
           auto *PI = PredInfo->getPredicateInfoFor(ReplacedInst);
-          if (!PI || DominatingLeader != PI->OriginalOp)
+          if (!PI || DominatingLeader != PI->OriginalOp) {
+            if (!canBeReplacedBy(ReplacedInst, DominatingLeader))
+              continue;
             patchReplacementInstruction(ReplacedInst, DominatingLeader);
+          }
+
+          LLVM_DEBUG(dbgs()
+                     << "Found replacement " << *DominatingLeader << " for "
+                     << *U->get() << " in " << *(U->getUser()) << "\n");
           U->set(DominatingLeader);
           // This is now a use of the dominating leader, which means if the
           // dominating leader was dead, it's now live!
diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index 65c1669f92b4..47a704925596 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -3508,6 +3508,17 @@ void llvm::patchReplacementInstruction(Instruction *I, Value *Repl) {
   else if (!isa<LoadInst>(I))
     ReplInst->andIRFlags(I);

+  // Handle attributes.
+  if (auto *CB1 = dyn_cast<CallBase>(ReplInst)) {
+    if (auto *CB2 = dyn_cast<CallBase>(I)) {
+      bool Success = CB1->tryIntersectAttributes(CB2);
+      assert(Success && "We should not be trying to sink callbases "
+                        "with non-intersectable attributes");
+      // For NDEBUG Compile.
+      (void)Success;
+    }
+  }
+
   // FIXME: If both the original and replacement value are part of the
   // same control-flow region (meaning that the execution of one
   // guarantees the execution of the other), then we can combine the

define i1 @bucket(i32 noundef %x) {
  %cmp1 = icmp sgt i32 %x, 0
  %ctpop1 = tail call range(i32 1, 32) i32 @llvm.ctpop.i32(i32 %x)
  %cmp2 = icmp samesign ult i32 %ctpop1, 2
  %cond = select i1 %cmp1, i1 %cmp2, i1 false
  br i1 %cond, label %if.then, label %if.else

if.else:                                          ; preds = %0
  %ctpop2 = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 %x)
  %res = icmp eq i32 %ctpop2, 1
  ret i1 %res

if.then:                                          ; preds = %0
  ret i1 false
}

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

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

[GVNPass] Range attribute should be handled after CSE

Reproducer: https://alive2.llvm.org/ce/z/HAnoKn
```
define i1 @src(i32 noundef %x) {
  %cmp1 = icmp sgt i32 %x, 0
  %ctpop1 = tail call range(i32 1, 32) i32 @llvm.ctpop.i32(i32 %x)
  %cmp2 = icmp samesign ult i32 %ctpop1, 2
  %cond = select i1 %cmp1, i1 %cmp2, i1 false
  br i1 %cond, label %if.then, label %if.else

if.else:
  %ctpop2 = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 %x)
  %res = icmp eq i32 %ctpop2, 1
  ret i1 %res

if.then:
  ret i1 false
}

define i1 @tgt(i32 noundef %x) {
  %cmp1 = icmp sgt i32 %x, 0
  %ctpop1 = tail call range(i32 1, 32) i32 @llvm.ctpop.i32(i32 %x)
  %cmp2 = icmp samesign ult i32 %ctpop1, 2
  %cond = select i1 %cmp1, i1 %cmp2, i1 false
  br i1 %cond, label %if.then, label %if.else

if.else:
  %res = icmp eq i32 %ctpop1, 1
  ret i1 %res

if.then:
  ret i1 false
}
```
```

----------------------------------------
define i1 @src(i32 noundef %x) {
#0:
  %cmp1 = icmp sgt i32 noundef %x, 0
  %ctpop1 = ctpop i32 noundef %x
  %#range_0_%ctpop1 = !range i32 %ctpop1, i32 1, i32 32
  %cmp2 = icmp samesign ult i32 %#range_0_%ctpop1, 2
  %cond = select i1 %cmp1, i1 %cmp2, i1 0
  br i1 %cond, label %if.then, label %if.else

if.else:
  %ctpop2 = ctpop i32 noundef %x
  %#range_1_%ctpop2 = !range i32 %ctpop2, i32 0, i32 33
  %res = icmp eq i32 %#range_1_%ctpop2, 1
  ret i1 %res

if.then:
  ret i1 0
}
=>
define i1 @tgt(i32 noundef %x) {
#0:
  %cmp1 = icmp sgt i32 noundef %x, 0
  %ctpop1 = ctpop i32 noundef %x
  %#range_0_%ctpop1 = !range i32 %ctpop1, i32 1, i32 32
  %cmp2 = icmp samesign ult i32 %#range_0_%ctpop1, 2
  %cond = select i1 %cmp1, i1 %cmp2, i1 0
  br i1 %cond, label %if.then, label %if.else

if.else:
  %res = icmp eq i32 %#range_0_%ctpop1, 1
  ret i1 %res

if.then:
  ret i1 0
}
Transformation doesn't verify!

ERROR: Target is more poisonous than source

Example:
i32 noundef %x = #x00000000 (0)

Source:
i1 %cmp1 = #x0 (0)
i32 %ctpop1 = #x00000000 (0)
i32 %#range_0_%ctpop1 = poison
i1 %cmp2 = poison
i1 %cond = #x0 (0)
  >> Jump to %if.else
i32 %ctpop2 = #x00000000 (0)
i32 %#range_1_%ctpop2 = #x00000000 (0)
i1 %res = #x0 (0)

Target:
i1 %cmp1 = #x0 (0)
i32 %ctpop1 = #x00000000 (0)
i32 %#range_0_%ctpop1 = poison
i1 %cmp2 = poison
i1 %cond = #x0 (0)
  >> Jump to %if.else
i1 %res = poison
Source value: #x0 (0)
Target value: poison
```

Reported by @pranavk. See https://github.com/llvm/llvm-project/pull/100899#issuecomment-2442780517.


commit 030829a7e53fad0eab9b87b5dd49427e9fb13303
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Mon Dec 23 16:53:37 2024 -0800

    [SLP]Drop samesign flag if the vector node has reduced bitwidth

    If the operands of the icmp instructions has reduced bitwidth after
    MinBitwidth analysis, need to drop samesign flag to preserve correctness
    of the transformation.

    Fixes #120823

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index d22379429d00..b5d68c075b98 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -15483,6 +15483,8 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) {
       CmpInst::Predicate P0 = cast<CmpInst>(VL0)->getPredicate();
       Value *V = Builder.CreateCmp(P0, L, R);
       propagateIRFlags(V, E->Scalars, VL0);
+      if (auto *ICmp = dyn_cast<ICmpInst>(V); ICmp && It == MinBWs.end())
+        ICmp->setSameSign(/*B=*/false);
       // Do not cast for cmps.
       VecTy = cast<FixedVectorType>(V->getType());
       V = FinalShuffle(V, E);

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

[SLPVectorizer] `samesign` flags should be dropped after narrowing down the width of operands

Reproducer: https://alive2.llvm.org/ce/z/AvBhy9
```
; bin/opt -passes=slp-vectorizer test.ll -S
target triple = "x86_64-unknown-linux-gnu"

define i1 @test() {
entry:
  %and.i1698.1.i = zext i16 0 to i32
  %and19.i1699.2.i = and i32 %and.i1698.1.i, 0
  %and.i1698.2.i = zext i16 0 to i32
  %cmp25.i1700.2.i2 = icmp samesign uge i32 %and19.i1699.2.i, %and.i1698.1.i
  %and19.i1699.11841.i = and i32 %and.i1698.2.i, 0
  %cmp25.i1700.11842.i3 = icmp samesign uge i32 %and19.i1699.11841.i, %and.i1698.2.i
  %and.i1698.1.1.i = zext i16 0 to i32
  %and19.i1699.2.1.i = and i32 %and.i1698.1.1.i, 0
  %0 = add i16 1, 0
  %and.i1698.2.1.i = zext i16 %0 to i32
  %cmp25.i1700.2.1.i4 = icmp samesign uge i32 %and19.i1699.2.1.i, %and.i1698.1.1.i
  %and19.i1699.21846.i = and i32 %and.i1698.2.1.i, 0
  %cmp25.i1700.21847.i = icmp samesign uge i32 %and19.i1699.21846.i, %and.i1698.2.1.i
  ret i1 %cmp25.i1700.21847.i
}
```
```
define i1 @test() {
entry:
  %0 = add i16 1, 0
  %1 = insertelement <4 x i16> <i16 poison, i16 0, i16 0, i16 0>, i16 %0, i32 0
  %2 = trunc <4 x i16> %1 to <4 x i1>
  %3 = and <4 x i1> %2, zeroinitializer
  %4 = icmp samesign uge <4 x i1> %3, %2
  %5 = extractelement <4 x i1> %4, i32 0
  ret i1 %5
}
```
```

----------------------------------------
define i1 @src() {
entry:
  %#0 = add i16 1, 0
  %and.i1698.2.1.i = zext i16 %#0 to i32
  %and19.i1699.21846.i = and i32 %and.i1698.2.1.i, 0
  %cmp25.i1700.21847.i = icmp samesign uge i32 %and19.i1699.21846.i, %and.i1698.2.1.i
  ret i1 %cmp25.i1700.21847.i
}
=>
define i1 @src() {
entry:
  %#0 = add i16 1, 0
  %#1 = insertelement <4 x i16> { poison, 0, 0, 0 }, i16 %#0, i32 0
  %#2 = trunc <4 x i16> %#1 to <4 x i1>
  %#3 = and <4 x i1> %#2, { 0, 0, 0, 0 }
  %#4 = icmp samesign uge <4 x i1> %#3, %#2
  %#5 = extractelement <4 x i1> %#4, i32 0
  ret i1 %#5
}
Transformation doesn't verify!

ERROR: Target is more poisonous than source

Example:

Source:
i16 %#0 = #x0001 (1)
i32 %and.i1698.2.1.i = #x00000001 (1)
i32 %and19.i1699.21846.i = #x00000000 (0)
i1 %cmp25.i1700.21847.i = #x0 (0)

Target:
i16 %#0 = #x0001 (1)
<4 x i16> %#1 = < #x0001 (1), #x0000 (0), #x0000 (0), #x0000 (0) >
<4 x i1> %#2 = < #x1 (1), #x0 (0), #x0 (0), #x0 (0) >
<4 x i1> %#3 = < #x0 (0), #x0 (0), #x0 (0), #x0 (0) >
<4 x i1> %#4 = < poison, #x1 (1), #x1 (1), #x1 (1) >
i1 %#5 = poison
Source value: #x0 (0)
Target value: poison

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