commit 2601d6f189cf1d4e4e77a7cba83e5d32c87bf079
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Tue Aug 6 12:27:36 2024 -0700

    [SLP]Fix PR102187: do not insert extractelement before landingpad instruction.

    Landingpad instruction must be the very first instruction after the phi
    nodes, so need to inser extractelement/shuffles after this instruction.

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

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 9589d306581e..5c8873853a73 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -14049,12 +14049,19 @@ Value *BoUpSLP::vectorizeTree(
              "ExternallyUsedValues map or remain as scalar in vectorized "
              "instructions");
       if (auto *VecI = dyn_cast<Instruction>(Vec)) {
-        if (auto *PHI = dyn_cast<PHINode>(VecI))
-          Builder.SetInsertPoint(PHI->getParent(),
-                                 PHI->getParent()->getFirstNonPHIIt());
-        else
+        if (auto *PHI = dyn_cast<PHINode>(VecI)) {
+          if (PHI->getParent()->isLandingPad())
+            Builder.SetInsertPoint(
+                PHI->getParent(),
+                std::next(
+                    PHI->getParent()->getLandingPadInst()->getIterator()));
+          else
+            Builder.SetInsertPoint(PHI->getParent(),
+                                   PHI->getParent()->getFirstNonPHIIt());
+        } else {
           Builder.SetInsertPoint(VecI->getParent(),
                                  std::next(VecI->getIterator()));
+        }
       } else {
         Builder.SetInsertPoint(&F->getEntryBlock(), F->getEntryBlock().begin());
       }
@@ -14080,11 +14087,18 @@ Value *BoUpSLP::vectorizeTree(
             auto VecIt = VectorCasts.find(Key);
             if (VecIt == VectorCasts.end()) {
               IRBuilderBase::InsertPointGuard Guard(Builder);
-              if (auto *IVec = dyn_cast<PHINode>(Vec))
-                Builder.SetInsertPoint(
-                    IVec->getParent()->getFirstNonPHIOrDbgOrLifetime());
-              else if (auto *IVec = dyn_cast<Instruction>(Vec))
+              if (auto *IVec = dyn_cast<PHINode>(Vec)) {
+                if (IVec->getParent()->isLandingPad())
+                  Builder.SetInsertPoint(IVec->getParent(),
+                                         std::next(IVec->getParent()
+                                                       ->getLandingPadInst()
+                                                       ->getIterator()));
+                else
+                  Builder.SetInsertPoint(
+                      IVec->getParent()->getFirstNonPHIOrDbgOrLifetime());
+              } else if (auto *IVec = dyn_cast<Instruction>(Vec)) {
                 Builder.SetInsertPoint(IVec->getNextNonDebugInstruction());
+              }
               Vec = Builder.CreateIntCast(
                   Vec,
                   getWidenedType(

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

define void @test() personality ptr null {
bb:
  invoke void null()
          to label %bb65 unwind label %bb4

bb2:                                              ; No predecessors!
  invoke void null()
          to label %bb65 unwind label %bb4

bb4:                                              ; preds = %bb2, %bb
  %phi5 = phi i32 [ 0, %bb ], [ 0, %bb2 ]
  %phi6 = phi i32 [ 0, %bb ], [ 0, %bb2 ]
  %landingpad = landingpad { ptr, i32 }
          cleanup
  call void null(i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5, i32 %phi5)
  ret void

bb65:                                             ; preds = %bb2, %bb
  ret void
}

To reproduce run opt with
[Test.ll.tgz](https://github.com/user-attachments/files/16513795/Test.ll.tgz)
using `-passes slp-vectorizer -slp-threshold=-99999`

Reproducer https://godbolt.org/z/f4szGsMYd

```
The unwind destination does not have an exception handling instruction!
  %invoke = invoke i64 null(ptr addrspace(1) null, i32 0, i64 0, i32 0)
          to label %bb65 unwind label %bb4
The unwind destination does not have an exception handling instruction!
  %invoke3 = invoke i64 null(ptr addrspace(1) null, i32 0, i64 0, i32 0)
          to label %bb65 unwind label %bb4
LandingPadInst not the first non-PHI instruction in the block.
  %landingpad = landingpad { ptr, i32 }
          cleanup
LLVM ERROR: Broken module found, compilation aborted!
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/opt -o /app/output.s -S -passes slp-vectorizer -slp-threshold=-99999 <source>
1.	Running pass "verify" on module "<source>"
 #0 0x0000000004f1d2d8 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4f1d2d8)
 #1 0x0000000004f1aa4c SignalHandler(int) Signals.cpp:0:0
 #2 0x0000788c1ca42520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x0000788c1ca969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x0000788c1ca42476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x0000788c1ca287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x00000000007b40fd llvm::json::operator==(llvm::json::Value const&, llvm::json::Value const&) (.cold) JSON.cpp:0:0
 #7 0x0000000004e571e8 (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4e571e8)
 #8 0x0000000004d53550 llvm::VerifierPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4d53550)
 #9 0x00000000008d8a7e llvm::detail::PassModel<llvm::Module, llvm::VerifierPass, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8d8a7e)
#10 0x0000000004d17270 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4d17270)
#11 0x00000000008e37f2 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+0x8e37f2)
#12 0x00000000008d671c optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8d671c)
#13 0x0000788c1ca29d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#14 0x0000788c1ca29e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#15 0x00000000008cdb7e _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8cdb7e)
Program terminated with signal: SIGSEGV
Compiler returned: 139
```


commit 56140a8258a3498cfcd9f0f05c182457d43cbfd2
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Thu Aug 15 07:57:37 2024 -0700

    [SLP]Fix PR104422: Wrong value truncation

    The minbitwidth restrictions can be skipped only for immediate reduced
    values, for other nodes still need to check if external users allow
    bitwidth reduction.

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

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 81841a8f6928..87b4ed599b5b 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -15663,7 +15663,8 @@ bool BoUpSLP::collectValuesToDemote(
   if (any_of(E.Scalars, [&](Value *V) {
         return !all_of(V->users(), [=](User *U) {
           return getTreeEntry(U) ||
-                 (UserIgnoreList && UserIgnoreList->contains(U)) ||
+                 (E.Idx == 0 && UserIgnoreList &&
+                  UserIgnoreList->contains(U)) ||
                  (!isa<CmpInst>(U) && U->getType()->isSized() &&
                   !U->getType()->isScalableTy() &&
                   DL->getTypeSizeInBits(U->getType()) <= BitWidth);

opt -S --passes=slp-vectorizer < %s -slp-threshold=-10

[SLPVectorizer] Wrong value truncation

- There seems to be an issue with SLPVectorizer. In the following example, a 2-byte wide value is incorrectly truncated:

```
define i64 @test(ptr addrspace(1) %arr, i32 %a) {
entry:
  br label %loop

loop:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %local_1_7 = phi i64 [ 0, %entry ], [ %4, %loop ]
  %0 = sext i32 %a to i64
  %1 = add nsw i64 %0, 4294967297
  %2 = add i64 %1, %local_1_7
  %3 = and i64 %1, 1
  %4 = add i64 %2, %3
  %iv.next = add nuw nsw i64 %iv, 1
  %5 = icmp ugt i64 %iv, 355
  br i1 %5, label %exit, label %loop

exit:
  ret i64 %4
}
```
- In the loop we summarize the constant 4294967297 (`0x1'0000'0001`), but after running SLPVectorizer over the unrolled loop, the constant is truncated to `1`:
```
loop:
  %iv = phi i64 [ 0, %entry ], [ %iv.next.16, %loop ]
  %local_1_7 = phi i64 [ 0, %entry ], [ %op.rdx3, %loop ]
  %2 = add <16 x i32> %1, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
  %3 = sext <16 x i32> %2 to <16 x i64>
...
```
- Command to reproduce: `opt -passes=loop-unroll,slp-vectorizer -unroll-count=17`
- https://godbolt.org/z/zcPefTPzW
- Looks like the issue was caused by the  https://github.com/llvm/llvm-project/commit/7f2167868d8c1cedd3915883412b9c787a2f01db

@alexey-bataev Could you please take a look?

This probably needs an LLVM 19 backport?

/cherry-pick 65ac12d3c9877ecf5b97552364e7eead887d94eb 56140a8258a3498cfcd9f0f05c182457d43cbfd2


commit 9edc454ee601e04500529c98b753d3bd8f427d01
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Mon Oct 14 20:52:55 2024 +0800

    [InstCombine] Drop range attributes in `foldIsPowerOf2OrZero` (#112178)

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

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 453071f3f982..64bee4ab974e 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -935,9 +935,11 @@ static Value *foldSignedTruncationCheck(ICmpInst *ICmp0, ICmpInst *ICmp1,

 /// Fold (icmp eq ctpop(X) 1) | (icmp eq X 0) into (icmp ult ctpop(X) 2) and
 /// fold (icmp ne ctpop(X) 1) & (icmp ne X 0) into (icmp ugt ctpop(X) 1).
-/// Also used for logical and/or, must be poison safe.
+/// Also used for logical and/or, must be poison safe if range attributes are
+/// dropped.
 static Value *foldIsPowerOf2OrZero(ICmpInst *Cmp0, ICmpInst *Cmp1, bool IsAnd,
-                                   InstCombiner::BuilderTy &Builder) {
+                                   InstCombiner::BuilderTy &Builder,
+                                   InstCombinerImpl &IC) {
   CmpInst::Predicate Pred0, Pred1;
   Value *X;
   if (!match(Cmp0, m_ICmp(Pred0, m_Intrinsic<Intrinsic::ctpop>(m_Value(X)),
@@ -945,11 +947,19 @@ static Value *foldIsPowerOf2OrZero(ICmpInst *Cmp0, ICmpInst *Cmp1, bool IsAnd,
       !match(Cmp1, m_ICmp(Pred1, m_Specific(X), m_ZeroInt())))
     return nullptr;

-  Value *CtPop = Cmp0->getOperand(0);
-  if (IsAnd && Pred0 == ICmpInst::ICMP_NE && Pred1 == ICmpInst::ICMP_NE)
+  auto *CtPop = cast<Instruction>(Cmp0->getOperand(0));
+  if (IsAnd && Pred0 == ICmpInst::ICMP_NE && Pred1 == ICmpInst::ICMP_NE) {
+    // Drop range attributes and re-infer them in the next iteration.
+    CtPop->dropPoisonGeneratingAnnotations();
+    IC.addToWorklist(CtPop);
     return Builder.CreateICmpUGT(CtPop, ConstantInt::get(CtPop->getType(), 1));
-  if (!IsAnd && Pred0 == ICmpInst::ICMP_EQ && Pred1 == ICmpInst::ICMP_EQ)
+  }
+  if (!IsAnd && Pred0 == ICmpInst::ICMP_EQ && Pred1 == ICmpInst::ICMP_EQ) {
+    // Drop range attributes and re-infer them in the next iteration.
+    CtPop->dropPoisonGeneratingAnnotations();
+    IC.addToWorklist(CtPop);
     return Builder.CreateICmpULT(CtPop, ConstantInt::get(CtPop->getType(), 2));
+  }

   return nullptr;
 }
@@ -3362,9 +3372,9 @@ Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
                                              /*IsLogical*/ false, Builder, Q))
     return V;

-  if (Value *V = foldIsPowerOf2OrZero(LHS, RHS, IsAnd, Builder))
+  if (Value *V = foldIsPowerOf2OrZero(LHS, RHS, IsAnd, Builder, *this))
     return V;
-  if (Value *V = foldIsPowerOf2OrZero(RHS, LHS, IsAnd, Builder))
+  if (Value *V = foldIsPowerOf2OrZero(RHS, LHS, IsAnd, Builder, *this))
     return V;

   // TODO: One of these directions is fine with logical and/or, the other could

define i1 @is_pow2or0_decrement_op(i8 %x) {
  %dec = add i8 %x, -1
  %and = and i8 %dec, %x
  %cmp = icmp eq i8 %and, 0
  ret i1 %cmp
}

define <2 x i1> @is_pow2_negate_op_vec(<2 x i32> %x) {
  %neg = sub <2 x i32> zeroinitializer, %x
  %and = and <2 x i32> %neg, %x
  %cmp = icmp eq <2 x i32> %and, %x
  %notzero = icmp ne <2 x i32> %x, zeroinitializer
  %r = and <2 x i1> %cmp, %notzero
  ret <2 x i1> %r
}

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

define i1 @is_pow2_ctpop_wrong_cmp_op1_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ult i32 %t0, 3
  %notzero = icmp ne i32 %x, 0
  %r = select i1 %notzero, i1 %cmp, i1 false
  ret i1 %r
}

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

define i1 @is_pow2_negate_op(i32 %x) {
  %neg = sub i32 0, %x
  %and = and i32 %neg, %x
  %cmp = icmp eq i32 %and, %x
  %notzero = icmp ne i32 %x, 0
  %r = and i1 %notzero, %cmp
  ret i1 %r
}

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

define i1 @not_pow2_nz_known_bits(i32 %xin) {
  %x = or i32 %xin, 1
  %cnt = call i32 @llvm.ctpop.i32(i32 %x)
  %r = icmp ne i32 %cnt, 1
  ret i1 %r
}

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

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

define i1 @is_pow2_nz_known_bits(i32 %xin) {
  %x = or i32 %xin, 64
  %cnt = call i32 @llvm.ctpop.i32(i32 %x)
  %r = icmp eq i32 %cnt, 1
  ret i1 %r
}

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

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

define i1 @is_power2_or_zero_with_range(i32 %x) {
  %ctpop = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp eq i32 %ctpop, 1
  %notzero = icmp eq i32 %x, 0
  %res = select i1 %notzero, i1 true, i1 %cmp
  ret i1 %res
}

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

define i1 @blsmsk_is_p2_or_z(i32 %xx, i32 %yy) {
  %x = or i32 %xx, %yy
  %xm1 = add i32 %x, -1
  %y = xor i32 %x, %xm1
  %r = icmp uge i32 %x, %y
  ret i1 %r
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <2 x i8> @llvm.ctpop.v2i8(<2 x i8>) #0

define <2 x i1> @isnot_pow2nor0_ctpop_commute_vec(<2 x i8> %x) {
  %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
  %cmp = icmp ne <2 x i8> %t0, splat (i8 1)
  %notzero = icmp ne <2 x i8> %x, zeroinitializer
  %r = and <2 x i1> %notzero, %cmp
  ret <2 x i1> %r
}

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

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

define i1 @is_pow2or0_ctpop_wrong_pred1(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ne i32 %t0, 1
  %iszero = icmp eq i32 %x, 0
  %r = or i1 %iszero, %cmp
  ret i1 %r
}

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

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

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

define i1 @is_pow2_non_zero_ne_1(i32 %x) {
  %notzero = icmp ne i32 %x, 0
  call void @llvm.assume(i1 %notzero)
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ne i32 %t0, 1
  ret i1 %cmp
}

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

define i1 @blsmsk_is_p2_or_z_fail(i32 %xx, i32 %yy) {
  %x = or i32 %xx, %yy
  %xm1 = add i32 %x, -1
  %y = xor i32 %x, %xm1
  %r = icmp ugt i32 %x, %y
  ret i1 %r
}

define i1 @blsmsk_is_p2_or_z_uge_xy_fail(i8 %xx, i8 %yy) {
  %x = or i8 %xx, %yy
  %xm1 = add i8 %x, -1
  %y = xor i8 %x, %xm1
  %r = icmp uge i8 %x, %y
  ret i1 %r
}

declare void @use(i32)

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

declare void @use_i1(i1)

define i1 @is_pow2or0_ctpop_logical_extra_uses(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  call void @use(i32 %t0)
  %cmp = icmp eq i32 %t0, 1
  call void @use_i1(i1 %cmp)
  %iszero = icmp eq i32 %x, 0
  call void @use_i1(i1 %iszero)
  %r = select i1 %iszero, i1 true, i1 %cmp
  ret i1 %r
}

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

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <2 x i8> @llvm.ctpop.v2i8(<2 x i8>) #0

define <2 x i1> @isnot_pow2_ctpop_commute_vec(<2 x i8> %x) {
  %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
  %cmp = icmp ugt <2 x i8> %t0, splat (i8 1)
  %iszero = icmp eq <2 x i8> %x, zeroinitializer
  %r = or <2 x i1> %cmp, %iszero
  ret <2 x i1> %r
}

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

define i1 @blsmsk_isnt_p2_or_z_fail_wrong_add(i32 %x, i32 %z) {
  %xm1 = add i32 %z, -1
  %y = xor i32 %x, %xm1
  %r = icmp ult i32 %y, %x
  ret i1 %r
}

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

define i1 @is_pow2_ctpop_wrong_pred2(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ult i32 %t0, 2
  %cmp2 = icmp sgt i32 %x, 0
  %r = and i1 %cmp2, %cmp
  ret i1 %r
}

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

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

define i1 @is_pow2or0_ctpop_swap_cmp(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp eq i32 %t0, 1
  %iszero = icmp eq i32 %x, 0
  %r = or i1 %cmp, %iszero
  ret i1 %r
}

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

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <2 x i8> @llvm.ctpop.v2i8(<2 x i8>) #0

define <2 x i1> @is_pow2or0_ctpop_commute_vec_wrong_pred3(<2 x i8> %x) {
  %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
  %cmp = icmp eq <2 x i8> %t0, splat (i8 1)
  %iszero = icmp eq <2 x i8> %x, zeroinitializer
  %r = and <2 x i1> %cmp, %iszero
  ret <2 x i1> %r
}

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

define i1 @is_pow2_decrement_op_logical(i8 %x) {
  %dec = add i8 %x, -1
  %and = and i8 %dec, %x
  %cmp = icmp eq i8 %and, 0
  %notzero = icmp ne i8 %x, 0
  %r = select i1 %cmp, i1 %notzero, i1 false
  ret i1 %r
}

define <2 x i1> @isnot_pow2or0_negate_op_vec(<2 x i32> %x) {
  %neg = sub <2 x i32> zeroinitializer, %x
  %and = and <2 x i32> %neg, %x
  %cmp = icmp ne <2 x i32> %and, %x
  ret <2 x i1> %cmp
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <2 x i8> @llvm.ctpop.v2i8(<2 x i8>) #0

define <2 x i1> @is_pow2or0_ctpop_commute_vec(<2 x i8> %x) {
  %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
  %cmp = icmp eq <2 x i8> %t0, splat (i8 1)
  %iszero = icmp eq <2 x i8> %x, zeroinitializer
  %r = or <2 x i1> %iszero, %cmp
  ret <2 x i1> %r
}

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

define i1 @is_pow2_negate_op_logical(i32 %x) {
  %neg = sub i32 0, %x
  %and = and i32 %neg, %x
  %cmp = icmp eq i32 %and, %x
  %notzero = icmp ne i32 %x, 0
  %r = select i1 %notzero, i1 %cmp, i1 false
  ret i1 %r
}

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

define i1 @isnot_pow2nor0_ctpop(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ne i32 %t0, 1
  %notzero = icmp ne i32 %x, 0
  %r = and i1 %notzero, %cmp
  ret i1 %r
}

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

define i1 @blsmsk_isnt_p2_or_z_ult_xy_fail(i8 %xx, i8 %yy) {
  %x = or i8 %xx, %yy
  %xm1 = add i8 %x, -1
  %y = xor i8 %x, %xm1
  %r = icmp ult i8 %x, %y
  ret i1 %r
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <2 x i8> @llvm.ctpop.v2i8(<2 x i8>) #0

define <2 x i1> @isnot_pow2nor0_wrong_pred3_ctpop_commute_vec(<2 x i8> %x) {
  %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
  %cmp = icmp ne <2 x i8> %t0, splat (i8 1)
  %notzero = icmp ne <2 x i8> %x, zeroinitializer
  %r = or <2 x i1> %cmp, %notzero
  ret <2 x i1> %r
}

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

define <2 x i1> @is_pow2or0_negate_op_vec(<2 x i32> %x) {
  %neg = sub <2 x i32> zeroinitializer, %x
  %and = and <2 x i32> %neg, %x
  %cmp = icmp eq <2 x i32> %and, %x
  ret <2 x i1> %cmp
}

define i1 @isnot_pow2or0_negate_op(i32 %x) {
  %neg = sub i32 0, %x
  %and = and i32 %neg, %x
  %cmp = icmp ne i32 %and, %x
  ret i1 %cmp
}

define <2 x i1> @not_pow2_or_z_known_bits_fail_wrong_cmp(<2 x i32> %xin) {
  %x = or <2 x i32> %xin, splat (i32 64)
  %cnt = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> %x)
  %r = icmp ugt <2 x i32> %cnt, splat (i32 2)
  ret <2 x i1> %r
}

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

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

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

define i1 @is_pow2_ctpop_wrong_cmp_op2(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ult i32 %t0, 2
  %notzero = icmp ne i32 %x, 1
  %r = and i1 %notzero, %cmp
  ret i1 %r
}

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

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

define i1 @is_pow2_ctpop_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ult i32 %t0, 2
  %notzero = icmp ne i32 %x, 0
  %r = select i1 %notzero, i1 %cmp, i1 false
  ret i1 %r
}

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

define i1 @isnot_pow2_decrement_op_logical(i8 %x) {
  %dec = add i8 %x, -1
  %and = and i8 %dec, %x
  %cmp = icmp ne i8 %and, 0
  %iszero = icmp eq i8 %x, 0
  %r = select i1 %iszero, i1 true, i1 %cmp
  ret i1 %r
}

define i1 @isnot_pow2_negate_op_logical(i32 %x) {
  %neg = sub i32 0, %x
  %and = and i32 %neg, %x
  %cmp = icmp ne i32 %and, %x
  %iszero = icmp eq i32 %x, 0
  %r = select i1 %cmp, i1 true, i1 %iszero
  ret i1 %r
}

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

define i1 @is_pow2or0_ctpop(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp eq i32 %t0, 1
  %iszero = icmp eq i32 %x, 0
  %r = or i1 %iszero, %cmp
  ret i1 %r
}

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

define i1 @blsmsk_is_p2_or_z_uge_yx(i8 %xx, i8 %yy) {
  %x = or i8 %xx, %yy
  %xm1 = add i8 %x, -1
  %y = xor i8 %x, %xm1
  %r = icmp uge i8 %y, %x
  ret i1 %r
}

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

define i1 @has_single_bit_inv(i32 %x) {
entry:
  %cmp1 = icmp eq i32 %x, 0
  %popcnt = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 %x)
  %cmp2 = icmp ugt i32 %popcnt, 1
  %sel = select i1 %cmp1, i1 true, i1 %cmp2
  ret i1 %sel
}

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

define i1 @is_pow2or0_negate_op(i32 %x) {
  %neg = sub i32 0, %x
  %and = and i32 %neg, %x
  %cmp = icmp eq i32 %and, %x
  ret i1 %cmp
}

define i1 @blsmsk_isnt_p2_or_z_ugt_yx_fail(i8 %xx, i8 %yy) {
  %x = or i8 %xx, %yy
  %xm1 = add i8 %x, -1
  %y = xor i8 %x, %xm1
  %r = icmp ugt i8 %y, %x
  ret i1 %r
}

define i1 @blsmsk_isnt_p2_or_z_fail(i32 %x) {
  %xm1 = add i32 %x, -1
  %y = xor i32 %x, %xm1
  %r = icmp ule i32 %y, %x
  ret i1 %r
}

define <2 x i1> @is_pow2_decrement_op_vec(<2 x i8> %x) {
  %dec = add <2 x i8> %x, splat (i8 -1)
  %and = and <2 x i8> %dec, %x
  %cmp = icmp eq <2 x i8> %and, zeroinitializer
  %notzero = icmp ne <2 x i8> %x, zeroinitializer
  %r = and <2 x i1> %notzero, %cmp
  ret <2 x i1> %r
}

declare void @use(i32)

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

declare void @use_i1(i1)

define i1 @isnot_pow2nor0_ctpop_extra_uses(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  call void @use(i32 %t0)
  %cmp = icmp ne i32 %t0, 1
  call void @use_i1(i1 %cmp)
  %notzero = icmp ne i32 %x, 0
  call void @use_i1(i1 %notzero)
  %r = and i1 %notzero, %cmp
  ret i1 %r
}

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

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

define i1 @isnot_pow2nor0_ctpop_wrong_pred1(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp eq i32 %t0, 1
  %notzero = icmp ne i32 %x, 0
  %r = and i1 %notzero, %cmp
  ret i1 %r
}

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

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

define i1 @isnot_pow2_ctpop(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 1
  %iszero = icmp eq i32 %x, 0
  %r = or i1 %iszero, %cmp
  ret i1 %r
}

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

declare void @use.i32(i32)

define i1 @blsmsk_isnt_p2_or_z_fail_multiuse(i32 %x) {
  %xm1 = add i32 %x, -1
  %y = xor i32 %x, %xm1
  call void @use.i32(i32 %y)
  %r = icmp ult i32 %y, %x
  ret i1 %r
}

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

define i1 @is_pow2or0_ctpop_wrong_pred2_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ne i32 %t0, 1
  %iszero = icmp ne i32 %x, 0
  %r = select i1 %iszero, i1 true, i1 %cmp
  ret i1 %r
}

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

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

declare void @use_i1(i1)

define i1 @is_pow2_ctpop_extra_uses(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ult i32 %t0, 2
  call void @use_i1(i1 %cmp)
  %notzero = icmp ne i32 %x, 0
  call void @use_i1(i1 %notzero)
  %r = and i1 %notzero, %cmp
  ret i1 %r
}

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

define i1 @blsmsk_isnt_p2_or_z_ult_yx(i8 %xx, i8 %yy) {
  %x = or i8 %xx, %yy
  %xm1 = add i8 %x, -1
  %y = xor i8 %x, %xm1
  %r = icmp ult i8 %y, %x
  ret i1 %r
}

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

define i1 @is_pow2or0_ctpop_wrong_cmp_op1_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp eq i32 %t0, 3
  %iszero = icmp eq i32 %x, 0
  %r = select i1 %iszero, i1 true, i1 %cmp
  ret i1 %r
}

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

define i1 @blsmsk_isnt_p2_or_z_fail_bad_xor(i32 %x, i32 %z) {
  %xm1 = add i32 %x, -1
  %y = xor i32 %z, %xm1
  %r = icmp ult i32 %y, %x
  ret i1 %r
}

declare void @use(i32)

define i1 @is_pow2or0_negate_op_extra_use2(i32 %x) {
  %neg = sub i32 0, %x
  %and = and i32 %neg, %x
  call void @use(i32 %and)
  %cmp = icmp eq i32 %and, %x
  ret i1 %cmp
}

define i1 @isnot_pow2_negate_op(i32 %x) {
  %neg = sub i32 0, %x
  %and = and i32 %neg, %x
  %cmp = icmp ne i32 %and, %x
  %iszero = icmp eq i32 %x, 0
  %r = or i1 %cmp, %iszero
  ret i1 %r
}

declare void @use(i32)

define i1 @is_pow2or0_negate_op_extra_use1(i32 %x) {
  %neg = sub i32 0, %x
  call void @use(i32 %neg)
  %and = and i32 %neg, %x
  %cmp = icmp eq i32 %and, %x
  ret i1 %cmp
}

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

define i1 @isnot_pow2_ctpop_wrong_cmp_op1_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 2
  %iszero = icmp eq i32 %x, 0
  %r = select i1 %iszero, i1 true, i1 %cmp
  ret i1 %r
}

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

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

define i1 @isnot_pow2_ctpop_wrong_cmp_op2_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 1
  %iszero = icmp eq i32 %x, 1
  %r = select i1 %iszero, i1 true, i1 %cmp
  ret i1 %r
}

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

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

define i1 @is_pow2_ctpop_wrong_cmp_op1(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ult i32 %t0, 3
  %notzero = icmp ne i32 %x, 0
  %r = and i1 %notzero, %cmp
  ret i1 %r
}

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

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <2 x i8> @llvm.ctpop.v2i8(<2 x i8>) #0

define <2 x i1> @is_pow2or0_ctpop_commute_vec_wrong_cmp_op1(<2 x i8> %x) {
  %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
  %cmp = icmp eq <2 x i8> %t0, <i8 -1, i8 1>
  %iszero = icmp eq <2 x i8> %x, zeroinitializer
  %r = or <2 x i1> %cmp, %iszero
  ret <2 x i1> %r
}

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

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

define i1 @isnot_pow2_ctpop_wrong_pred2_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 1
  %cmp2 = icmp slt i32 %x, 0
  %r = select i1 %cmp2, i1 true, i1 %cmp
  ret i1 %r
}

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

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

declare void @use_i1(i1)

define i1 @is_pow2_ctpop_extra_uses_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ult i32 %t0, 2
  call void @use_i1(i1 %cmp)
  %notzero = icmp ne i32 %x, 0
  call void @use_i1(i1 %notzero)
  %r = select i1 %notzero, i1 %cmp, i1 false
  ret i1 %r
}

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

define i1 @isnot_pow2or0_negate_op_commute3(i32 %p) {
  %x = urem i32 42, %p
  %neg = sub i32 0, %x
  %and = and i32 %x, %neg
  %cmp = icmp ne i32 %x, %and
  ret i1 %cmp
}

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

define i1 @is_pow2_ctpop_wrong_cmp_op2_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ult i32 %t0, 2
  %notzero = icmp ne i32 %x, 1
  %r = select i1 %notzero, i1 %cmp, i1 false
  ret i1 %r
}

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

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

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

define i1 @is_pow2_non_zero_eq_1(i32 %x) {
  %notzero = icmp ne i32 %x, 0
  call void @llvm.assume(i1 %notzero)
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp eq i32 %t0, 1
  ret i1 %cmp
}

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

declare void @use(i32)

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

declare void @use_i1(i1)

define i1 @isnot_pow2nor0_ctpop_logical_extra_uses(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  call void @use(i32 %t0)
  %cmp = icmp ne i32 %t0, 1
  call void @use_i1(i1 %cmp)
  %notzero = icmp ne i32 %x, 0
  call void @use_i1(i1 %notzero)
  %r = select i1 %notzero, i1 %cmp, i1 false
  ret i1 %r
}

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

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

define i1 @is_pow2or0_ctpop_wrong_pred2(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ne i32 %t0, 1
  %iszero = icmp ne i32 %x, 0
  %r = or i1 %iszero, %cmp
  ret i1 %r
}

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

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

define i1 @isnot_pow2_ctpop_wrong_cmp_op2(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 1
  %iszero = icmp eq i32 %x, 1
  %r = or i1 %iszero, %cmp
  ret i1 %r
}

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

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

define i1 @is_pow2_ctpop_wrong_pred1(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 2
  %notzero = icmp ne i32 %x, 0
  %r = and i1 %notzero, %cmp
  ret i1 %r
}

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

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

declare void @use_i1(i1)

define i1 @isnot_pow2_ctpop_extra_uses_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 1
  call void @use_i1(i1 %cmp)
  %iszero = icmp eq i32 %x, 0
  call void @use_i1(i1 %iszero)
  %r = select i1 %iszero, i1 true, i1 %cmp
  ret i1 %r
}

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

declare void @use(i32)

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

declare void @use_i1(i1)

define i1 @is_pow2or0_ctpop_extra_uses(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  call void @use(i32 %t0)
  %cmp = icmp eq i32 %t0, 1
  call void @use_i1(i1 %cmp)
  %iszero = icmp eq i32 %x, 0
  call void @use_i1(i1 %iszero)
  %r = or i1 %iszero, %cmp
  ret i1 %r
}

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

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

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

define i1 @is_pow2_non_zero_ult_2(i32 %x) {
  %notzero = icmp ne i32 %x, 0
  call void @llvm.assume(i1 %notzero)
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ult i32 %t0, 2
  ret i1 %cmp
}

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

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <2 x i8> @llvm.ctpop.v2i8(<2 x i8>) #0

define <2 x i1> @is_pow2_ctpop_commute_vec(<2 x i8> %x) {
  %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
  %cmp = icmp ult <2 x i8> %t0, splat (i8 2)
  %notzero = icmp ne <2 x i8> %x, zeroinitializer
  %r = and <2 x i1> %cmp, %notzero
  ret <2 x i1> %r
}

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

define i1 @isnot_pow2_decrement_op(i8 %x) {
  %dec = add i8 %x, -1
  %and = and i8 %dec, %x
  %cmp = icmp ne i8 %and, 0
  %iszero = icmp eq i8 %x, 0
  %r = or i1 %iszero, %cmp
  ret i1 %r
}

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

define i1 @isnot_pow2nor0_ctpop_wrong_cmp_op1_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ne i32 %t0, 5
  %notzero = icmp ne i32 %x, 0
  %r = select i1 %notzero, i1 %cmp, i1 false
  ret i1 %r
}

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

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

define i1 @is_pow2_ctpop_wrong_pred1_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 2
  %notzero = icmp ne i32 %x, 0
  %r = select i1 %notzero, i1 %cmp, i1 false
  ret i1 %r
}

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

define <2 x i1> @isnot_pow2or0_decrement_op_vec(<2 x i8> %x) {
  %dec = add <2 x i8> %x, splat (i8 -1)
  %and = and <2 x i8> %dec, %x
  %cmp = icmp ne <2 x i8> %and, zeroinitializer
  ret <2 x i1> %cmp
}

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

define i1 @is_pow2_ctpop_wrong_pred2_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ult i32 %t0, 2
  %cmp2 = icmp sgt i32 %x, 0
  %r = select i1 %cmp2, i1 %cmp, i1 false
  ret i1 %r
}

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

define i1 @blsmsk_isnt_p2_or_z_ugt_xy(i8 %xx, i8 %yy) {
  %x = or i8 %xx, %yy
  %xm1 = add i8 %x, -1
  %y = xor i8 %x, %xm1
  %r = icmp ugt i8 %x, %y
  ret i1 %r
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <2 x i8> @llvm.ctpop.v2i8(<2 x i8>) #0

define <2 x i1> @isnot_pow2nor0_ctpop_commute_vec_wrong_cmp_op1(<2 x i8> %x) {
  %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)
  %cmp = icmp ne <2 x i8> %t0, <i8 0, i8 -1>
  %notzero = icmp ne <2 x i8> %x, zeroinitializer
  %r = and <2 x i1> %cmp, %notzero
  ret <2 x i1> %r
}

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

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

define i1 @isnot_pow2nor0_ctpop_wrong_pred2_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp eq i32 %t0, 1
  %notzero = icmp eq i32 %x, 0
  %r = select i1 %notzero, i1 %cmp, i1 false
  ret i1 %r
}

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

define i1 @is_pow2or0_negate_op_commute1(i32 %p) {
  %x = srem i32 42, %p
  %neg = sub i32 0, %x
  %and = and i32 %x, %neg
  %cmp = icmp eq i32 %and, %x
  ret i1 %cmp
}

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

define i1 @is_pow2_or_z_known_bits(i32 %xin) {
  %x = or i32 %xin, -2147483648
  %cnt = call i32 @llvm.ctpop.i32(i32 %x)
  %r = icmp ult i32 %cnt, 2
  ret i1 %r
}

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

define <2 x i1> @is_pow2or0_decrement_op_vec(<2 x i8> %x) {
  %dec = add <2 x i8> %x, splat (i8 -1)
  %and = and <2 x i8> %dec, %x
  %cmp = icmp eq <2 x i8> %and, zeroinitializer
  ret <2 x i1> %cmp
}

define i1 @is_pow2_decrement_op(i8 %x) {
  %dec = add i8 %x, -1
  %and = and i8 %dec, %x
  %cmp = icmp eq i8 %and, 0
  %notzero = icmp ne i8 %x, 0
  %r = and i1 %cmp, %notzero
  ret i1 %r
}

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

define i1 @isnot_pow2_ctpop_wrong_pred2(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 1
  %cmp2 = icmp slt i32 %x, 0
  %r = or i1 %cmp2, %cmp
  ret i1 %r
}

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

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

define i1 @isnot_pow2_ctpop_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 1
  %iszero = icmp eq i32 %x, 0
  %r = select i1 %iszero, i1 true, i1 %cmp
  ret i1 %r
}

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

define i1 @isnot_pow2or0_negate_op_commute2(i32 %p) {
  %x = urem i32 42, %p
  %neg = sub i32 0, %x
  %and = and i32 %neg, %x
  %cmp = icmp ne i32 %x, %and
  ret i1 %cmp
}

define i1 @blsmsk_is_p2_or_z_fail_bad_cmp(i32 %x, i32 %z) {
  %xm1 = add i32 %x, -1
  %y = xor i32 %x, %xm1
  %r = icmp uge i32 %y, %z
  ret i1 %r
}

define <2 x i1> @isnot_pow2_decrement_op_vec(<2 x i8> %x) {
  %dec = add <2 x i8> %x, splat (i8 -1)
  %and = and <2 x i8> %dec, %x
  %cmp = icmp ne <2 x i8> %and, zeroinitializer
  %iszero = icmp eq <2 x i8> %x, zeroinitializer
  %r = or <2 x i1> %cmp, %iszero
  ret <2 x i1> %r
}

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

define i1 @is_pow2or0_ctpop_wrong_cmp_op1(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp eq i32 %t0, 2
  %iszero = icmp eq i32 %x, 0
  %r = or i1 %iszero, %cmp
  ret i1 %r
}

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

define i1 @blsmsk_is_p2_or_z_ule_yx_fail(i8 %xx, i8 %yy) {
  %x = or i8 %xx, %yy
  %xm1 = add i8 %x, -1
  %y = xor i8 %x, %xm1
  %r = icmp ule i8 %y, %x
  ret i1 %r
}

define <2 x i1> @not_pow2_or_z_known_bits(<2 x i32> %xin) {
  %x = or <2 x i32> %xin, splat (i32 64)
  %cnt = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> %x)
  %r = icmp ugt <2 x i32> %cnt, splat (i32 1)
  ret <2 x i1> %r
}

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

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

define <2 x i1> @isnot_pow2_negate_op_vec(<2 x i32> %x) {
  %neg = sub <2 x i32> zeroinitializer, %x
  %and = and <2 x i32> %neg, %x
  %cmp = icmp ne <2 x i32> %and, %x
  %iszero = icmp eq <2 x i32> %x, zeroinitializer
  %r = or <2 x i1> %iszero, %cmp
  ret <2 x i1> %r
}

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

define i1 @is_pow2or0_ctpop_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp eq i32 %t0, 1
  %iszero = icmp eq i32 %x, 0
  %r = select i1 %iszero, i1 true, i1 %cmp
  ret i1 %r
}

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

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

declare void @use_i1(i1)

define i1 @isnot_pow2_ctpop_extra_uses(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 1
  call void @use_i1(i1 %cmp)
  %iszero = icmp eq i32 %x, 0
  call void @use_i1(i1 %iszero)
  %r = or i1 %iszero, %cmp
  ret i1 %r
}

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

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

define i1 @is_power2_or_zero_inv_with_range(i32 %x) {
  %ctpop = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ne i32 %ctpop, 1
  %notzero = icmp ne i32 %x, 0
  %res = select i1 %notzero, i1 %cmp, i1 false
  ret i1 %res
}

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

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

define i1 @isnot_pow2nor0_ctpop_wrong_pred2(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp eq i32 %t0, 1
  %notzero = icmp eq i32 %x, 0
  %r = and i1 %notzero, %cmp
  ret i1 %r
}

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

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

define i1 @has_single_bit(i32 %x) {
entry:
  %cmp1 = icmp ne i32 %x, 0
  %popcnt = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 %x)
  %cmp2 = icmp ult i32 %popcnt, 2
  %sel = select i1 %cmp1, i1 %cmp2, i1 false
  ret i1 %sel
}

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

define i1 @is_pow2_fail_pr63327(i32 %x) {
  %nx = sub i32 0, %x
  %x_and_nx = and i32 %x, %nx
  %r = icmp sge i32 %x_and_nx, %x
  ret i1 %r
}

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

define i1 @is_pow2_ctpop(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ult i32 %t0, 2
  %notzero = icmp ne i32 %x, 0
  %r = and i1 %notzero, %cmp
  ret i1 %r
}

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

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

declare void @use.i32(i32)

define i1 @is_pow2_nz_known_bits_fail_multiuse(i32 %xin) {
  %x = or i32 %xin, 64
  %cnt = call i32 @llvm.ctpop.i32(i32 %x)
  call void @use.i32(i32 %cnt)
  %r = icmp eq i32 %cnt, 1
  ret i1 %r
}

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

define i1 @blsmsk_isnt_p2_or_z(i32 %x) {
  %xm1 = add i32 %x, -1
  %y = xor i32 %x, %xm1
  %r = icmp ult i32 %y, %x
  ret i1 %r
}

define i1 @isnot_pow2or0_decrement_op(i8 %x) {
  %dec = add i8 %x, -1
  %and = and i8 %dec, %x
  %cmp = icmp ne i8 %and, 0
  ret i1 %cmp
}

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

define i1 @not_pow2_nz_known_bits_fail_not_p2_test(i32 %xin) {
  %x = or i32 %xin, 1
  %cnt = call i32 @llvm.ctpop.i32(i32 %x)
  %r = icmp ne i32 %cnt, 2
  ret i1 %r
}

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

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

define i1 @isnot_pow2_ctpop_wrong_cmp_op1(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 2
  %iszero = icmp eq i32 %x, 0
  %r = or i1 %iszero, %cmp
  ret i1 %r
}

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

define i1 @blsmsk_is_p2_or_z_ule_xy(i8 %xx, i8 %yy) {
  %x = or i8 %xx, %yy
  %xm1 = add i8 %x, -1
  %y = xor i8 %x, %xm1
  %r = icmp ule i8 %x, %y
  ret i1 %r
}

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

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

define i1 @is_pow2_non_zero_ugt_1(i32 %x) {
  %notzero = icmp ne i32 %x, 0
  call void @llvm.assume(i1 %notzero)
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 1
  ret i1 %cmp
}

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

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

define i1 @isnot_pow2nor0_ctpop_swap_cmp(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ne i32 %t0, 1
  %notzero = icmp ne i32 %x, 0
  %r = and i1 %cmp, %notzero
  ret i1 %r
}

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

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

define i1 @isnot_pow2nor0_ctpop_logical(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ne i32 %t0, 1
  %notzero = icmp ne i32 %x, 0
  %r = select i1 %notzero, i1 %cmp, i1 false
  ret i1 %r
}

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

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

define i1 @isnot_pow2nor0_ctpop_wrong_cmp_op1(i32 %x) {
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ne i32 %t0, 4
  %notzero = icmp ne i32 %x, 0
  %r = and i1 %notzero, %cmp
  ret i1 %r
}

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

[InstCombine] `range` attribute should be dropped in `foldIsPowerOf2OrZero`

Reproducer: https://alive2.llvm.org/ce/z/u62KKP (Please use latest alive2 with https://github.com/AliveToolkit/alive2/pull/1097)
```
define i1 @src(i32 %x) {
  %t0 = tail call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ne i32 %t0, 1
  %notzero = icmp ne i32 %x, 0
  %r = select i1 %notzero, i1 %cmp, i1 false
  ret i1 %r
}

define i1 @tgt(i32 %x) {
  %t0 = tail call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 %x)
  %r = icmp ugt i32 %t0, 1
  ret i1 %r
}
```
```
----------------------------------------
define i1 @src(i32 %x) {
#0:
  %t0 = ctpop i32 %x
  %#range_0_%t0 = !range i32 %t0, i32 1, i32 33
  %cmp = icmp ne i32 %#range_0_%t0, 1
  %notzero = icmp ne i32 %x, 0
  %r = select i1 %notzero, i1 %cmp, i1 0
  ret i1 %r
}
=>
define i1 @tgt(i32 %x) {
#0:
  %t0 = ctpop i32 %x
  %#range_0_%t0 = !range i32 %t0, i32 1, i32 33
  %r = icmp ugt i32 %#range_0_%t0, 1
  ret i1 %r
}
Transformation doesn't verify!

ERROR: Target is more poisonous than source

Example:
i32 %x = #x00000000 (0)

Source:
i32 %t0 = #x00000000 (0)
i32 %#range_0_%t0 = poison
i1 %cmp = poison
i1 %notzero = #x0 (0)
i1 %r = #x0 (0)

Target:
i32 %t0 = #x00000000 (0)
i32 %#range_0_%t0 = poison
i1 %r = poison
Source value: #x0 (0)
Target value: poison
```


commit 2d61692d4b75b7d92b44bfafb1011c1723955151
Author: Matt Arsenault <Matthew.Arsenault@amd.com>
Date:   Thu May 23 19:31:33 2024 +0200

    Attributor: Do not assume function context in AANoCapture (#91462)

    If the calling function has the null_pointer_is_valid attribute, somehow
    a null constant reaches here. I'm not sure why exactly, it doesn't
    happen for other types of constants.

    Fixes #87856

diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
index 41b66aafe7d3..1b3bf3c732ed 100644
--- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
+++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
@@ -5690,6 +5690,9 @@ bool AANoCapture::isImpliedByIR(Attributor &A, const IRPosition &IRP,
     return V.use_empty();

   // You cannot "capture" null in the default address space.
+  //
+  // FIXME: This should use NullPointerIsDefined to account for the function
+  // attribute.
   if (isa<UndefValue>(V) || (isa<ConstantPointerNull>(V) &&
                              V.getType()->getPointerAddressSpace() == 0)) {
     return true;
@@ -5899,10 +5902,13 @@ ChangeStatus AANoCaptureImpl::updateImpl(Attributor &A) {

   const Function *F =
       isArgumentPosition() ? IRP.getAssociatedFunction() : IRP.getAnchorScope();
-  assert(F && "Expected a function!");
-  const IRPosition &FnPos = IRPosition::function(*F);
+
+  // TODO: Is the checkForAllUses below useful for constants?
+  if (!F)
+    return indicatePessimisticFixpoint();

   AANoCapture::StateType T;
+  const IRPosition &FnPos = IRPosition::function(*F);

   // Readonly means we cannot capture through memory.
   bool IsKnown;

define void @null_ptr_is_valid_call_with_null() #0 {
;
  call void @store_as0(ptr null)
  ret void
}

define void @null_ptr_is_valid_call_with_undef() #0 {
;
  call void @store_as0(ptr undef)
  ret void
}

define void @store_as0(ptr %0) {
;
  store i16 0, ptr %0, align 2
  ret void
}

define void @call_store_as1() {
;
  call void @store_as1(ptr addrspace(1) null)
  ret void
}

define void @store_as1(ptr addrspace(1) %arg) {
;
  store i16 0, ptr addrspace(1) %arg, align 2
  ret void
}

attributes #0 = { null_pointer_is_valid }
;.
;.

[attributor] Crash on `null_pointer_is_valid` function

With

```
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-none-linux-android28"

; Function Attrs: null_pointer_is_valid
define i64 @foo() #0 {
  call fastcc void @bar(ptr null)
  ret i64 0
}

define fastcc void @bar(ptr %0) {
  store i16 0, ptr %0, align 2
  ret void
}

attributes #0 = { null_pointer_is_valid }
```

and running

```
opt -passes=attributor file.ll
```

we crash with

```
opt: llvm-project/llvm/lib/Transforms/IPO/AttributorAttributes.cpp:5901: virtual ChangeStatus (anonymous namespace)::AANoCaptureImpl::updateImpl(Attributor &): Assertion `F && "Expected a function!"' 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 -passes=attributor reduced.ll
 #0 0x000000000165bf38 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (llvm-project/build/Release/bin/opt+0x165bf38)
 #1 0x0000000001659a40 llvm::sys::RunSignalHandlers() (llvm-project/build/Release/bin/opt+0x1659a40)
 #2 0x000000000165c938 SignalHandler(int) Signals.cpp:0:0
 #3 0x00007f3ec923e6f0 __restore_rt (/lib64/libc.so.6+0x3e6f0)
 #4 0x00007f3ec928b94c __pthread_kill_implementation (/lib64/libc.so.6+0x8b94c)
 #5 0x00007f3ec923e646 gsignal (/lib64/libc.so.6+0x3e646)
 #6 0x00007f3ec92287f3 abort (/lib64/libc.so.6+0x287f3)
 #7 0x00007f3ec922871b _nl_load_domain.cold (/lib64/libc.so.6+0x2871b)
 #8 0x00007f3ec9237386 (/lib64/libc.so.6+0x37386)
 #9 0x0000000002f2a65b (anonymous namespace)::AANoCaptureImpl::updateImpl(llvm::Attributor&) AttributorAttributes.cpp:0:0
#10 0x0000000002ec8492 llvm::AbstractAttribute::update(llvm::Attributor&) (llvm-project/build/Release/bin/opt+0x2ec8492)
#11 0x0000000002ed3b83 llvm::Attributor::updateAA(llvm::AbstractAttribute&) (llvm-project/build/Release/bin/opt+0x2ed3b83)
#12 0x0000000002eec289 llvm::AANoCapture const* llvm::Attributor::getOrCreateAAFor<llvm::AANoCapture>(llvm::IRPosition, llvm::AbstractAttribute const*, llvm::DepClassTy, bool, bool) Attributor.cpp:0:0
#13 0x0000000002f1ab57 (anonymous namespace)::AANoAliasCallSiteArgument::updateImpl(llvm::Attributor&) AttributorAttributes.cpp:0:0
#14 0x0000000002ec8492 llvm::AbstractAttribute::update(llvm::Attributor&) (llvm-project/build/Release/bin/opt+0x2ec8492)
#15 0x0000000002ed3b83 llvm::Attributor::updateAA(llvm::AbstractAttribute&) (llvm-project/build/Release/bin/opt+0x2ed3b83)
#16 0x0000000002efba19 llvm::AANoAlias const* llvm::Attributor::getOrCreateAAFor<llvm::AANoAlias>(llvm::IRPosition, llvm::AbstractAttribute const*, llvm::DepClassTy, bool, bool) Attributor.cpp:0:0
#17 0x0000000002ede880 void llvm::Attributor::checkAndQueryIRAttr<(llvm::Attribute::AttrKind)20, llvm::AANoAlias>(llvm::IRPosition const&, llvm::AttributeSet) (llvm-project/build/Release/bin/opt+0x2ede880)
#18 0x0000000002edd545 llvm::Attributor::identifyDefaultAbstractAttributes(llvm::Function&) (llvm-project/build/Release/bin/opt+0x2edd545)
#19 0x0000000002ee0800 runAttributorOnFunctions(llvm::InformationCache&, llvm::SetVector<llvm::Function*, llvm::SmallVector<llvm::Function*, 0u>, llvm::DenseSet<llvm::Function*, llvm::DenseMapInfo<llvm::Function*, void>>, 0u>&, llvm::AnalysisGetter&, llvm::CallGraphUpdater&, bool, bool) Attributor.cpp:0:0
#20 0x0000000002edfc41 llvm::AttributorPass::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (llvm-project/build/Release/bin/opt+0x2edfc41)
#21 0x0000000002b6fcdd llvm::detail::PassModel<llvm::Module, llvm::AttributorPass, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) PassBuilderPipelines.cpp:0:0
#22 0x0000000001853e56 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (llvm-project/build/Release/bin/opt+0x1853e56)
#23 0x0000000002afaa4b 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) (llvm-project/build/Release/bin/opt+0x2afaa4b)
#24 0x0000000001622f36 optMain (llvm-project/build/Release/bin/opt+0x1622f36)
```

cc @arsenm

Just returning on the null function seems to work, but I don't understand exactly why it reaches here. AANoCapture::isImpliedByIR is incorrectly reimplementing NullPointerIsDefined but fixing that doesn't seem to help any


commit 29f3a352068ce562bcb65e18a676c82a9991583c
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Sun Feb 16 20:18:29 2025 +0800

    [InstCombine] Do not keep samesign when speculatively executing icmps (#127007)

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

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 96d6db2ba5bf..76020d2b1dbf 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -5637,6 +5637,11 @@ Instruction *InstCombinerImpl::foldICmpWithMinMax(Instruction &I,
       return false;
     return std::nullopt;
   };
+  // Remove samesign here since it is illegal to keep it when we speculatively
+  // execute comparisons. For example, `icmp samesign ult umax(X, -46), -32`
+  // cannot be decomposed into `(icmp samesign ult X, -46) or (icmp samesign ult
+  // -46, -32)`. `X` is allowed to be non-negative here.
+  Pred = static_cast<CmpInst::Predicate>(Pred);
   auto CmpXZ = IsCondKnownTrue(simplifyICmpInst(Pred, X, Z, Q));
   auto CmpYZ = IsCondKnownTrue(simplifyICmpInst(Pred, Y, Z, Q));
   if (!CmpXZ.has_value() && !CmpYZ.has_value())

define i1 @pr126974(i8 %x) {
entry:
  %cond = icmp sgt i8 %x, -2
  br i1 %cond, label %if.then, label %if.else

if.then:                                          ; preds = %entry
  %umax = call i8 @llvm.umax.i8(i8 %x, i8 -46)
  %cmp = icmp samesign ult i8 %umax, -32
  ret i1 %cmp

if.else:                                          ; preds = %entry
  ret i1 false
}

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

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

[RISC-V] Miscompile using rv64gcv

Testcase:
```c
int a[][21][21];
void b(int c, int d, int e, short f, _Bool g, char h, char i, int j, int k,
       int l, unsigned char m, int n, char o, int p, long long q[],
       unsigned short r[][10], unsigned s[][10],
       unsigned long long t[][10][10][10], unsigned long long u[][10][10][10],
       int w[][10][10][10][10], _Bool x) {
  for (signed z = 0; z < (char)m + 3; z = 4)
    for (short aa = ({
                      __typeof__(0) ab = 173;
                      __typeof__(0) ac = ({
                        __typeof__(0) ab = m;
                        ab;
                      });
                      ab > ac ? ab : ac;
                    }) -
                    171;
         aa < 9; aa = k)
      a[z][aa][aa] = ~0;
}
typedef int ad;
int printf(const char *, ...);
long long ae;
void af(long long *ae, int v) { *ae ^= v; }
int c;
int d;
int e;
short f;
_Bool g;
char h;
char i;
int j;
int k = 2805750831;
int l;
char m;
int n;
char o;
int p;
long long q[0];
unsigned short r[0][10];
unsigned s[0][10];
unsigned long long t[0][10][10][10];
unsigned long long u[0][10][10][10];
int w[0][10][10][10][10];
_Bool x;
int a[21][21][21];
void ag() {
  for (ad y = 0; y < 10; ++y)
    for (ad ah = 0; ah < 10; ++ah)
      for (ad ai = 0; ai < 10; ++ai)
        af(&ae, a[y][ah][ai]);
}
int main() {
  b(c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, w, x);
  ag();
  printf("%llu\n", ae);
}
```

Commands:
```
# riscv
$ QEMU_CPU=rv64,vlen=128,rvv_ta_all_1s=true,rvv_ma_all_1s=true,v=true,vext_spec=v1.0,zve32f=true,zve64f=true timeout --verbose -k 0.1 4 /scratch/ewlu/daily-upstream-build/build-gcv/bin/qemu-riscv64 user-config.out 1
0

# x86
$ ./native.out 1
18446744073709551615
```

Godbolt: https://godbolt.org/z/85rz18rxY

Bisected to cfee344dda7394631f2177a15e56cfeee1d61fc4 as the first bad commit

I tried reducing the testcase down farther but was unsuccessful

Found via fuzzer. First detected 01/24/2025

Some manual simplification, reproduces on x86-64 `-O3` too:

```c
#include<stdio.h>

void f(int more_than_20, unsigned char zero) {
  int i = 0;
  while (i < (signed char)zero + 2) {
    int max = zero < 210 ? 210 : zero; // 210; has to be >127
    int j = max - 200; // 10
    while (j < 20) {
      printf("I should be printed once\n");
      j = more_than_20;
    }
    i = 2; // can be anything >2
  }
}

int main() {
  f(50, 0);
}
```

https://godbolt.org/z/qfn9PT6r5

Reproducer: https://alive2.llvm.org/ce/z/adparc

Further reduced: https://alive2.llvm.org/ce/z/5da83j


CoroSplitPass::run replacePrepare splitCoroutine updateCallGraphAfterCoroutineSplit

commit 853bff2122e1f42398587f76234c05d56f16318e
Author: Yuxuan Chen <ych@fb.com>
Date:   Thu Sep 12 10:45:20 2024 -0700

    [Coroutines] properly update CallGraph in CoroSplit (#107935)

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

    We weren't updating the call graph properly in CoroSplit. This crash is
    due to the await_suspend() function calling the coroutine, forming a
    multi-node SCC. The issue bisected to
    https://github.com/llvm/llvm-project/pull/79712 but I think this is red
    herring. We haven't been properly updating the call graph.

    Added an example of such code as a test case.

diff --git a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp
index dc3829d7f28e..8ea460badaad 100644
--- a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp
@@ -2080,12 +2080,13 @@ splitCoroutine(Function &F, SmallVectorImpl<Function *> &Clones,
   return Shape;
 }

-static void updateCallGraphAfterCoroutineSplit(
+static LazyCallGraph::SCC &updateCallGraphAfterCoroutineSplit(
     LazyCallGraph::Node &N, const coro::Shape &Shape,
     const SmallVectorImpl<Function *> &Clones, LazyCallGraph::SCC &C,
     LazyCallGraph &CG, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,
     FunctionAnalysisManager &FAM) {

+  auto *CurrentSCC = &C;
   if (!Clones.empty()) {
     switch (Shape.ABI) {
     case coro::ABI::Switch:
@@ -2105,13 +2106,16 @@ static void updateCallGraphAfterCoroutineSplit(
     }

     // Let the CGSCC infra handle the changes to the original function.
-    updateCGAndAnalysisManagerForCGSCCPass(CG, C, N, AM, UR, FAM);
+    CurrentSCC = &updateCGAndAnalysisManagerForCGSCCPass(CG, *CurrentSCC, N, AM,
+                                                         UR, FAM);
   }

   // Do some cleanup and let the CGSCC infra see if we've cleaned up any edges
   // to the split functions.
   postSplitCleanup(N.getFunction());
-  updateCGAndAnalysisManagerForFunctionPass(CG, C, N, AM, UR, FAM);
+  CurrentSCC = &updateCGAndAnalysisManagerForFunctionPass(CG, *CurrentSCC, N,
+                                                          AM, UR, FAM);
+  return *CurrentSCC;
 }

 /// Replace a call to llvm.coro.prepare.retcon.
@@ -2200,6 +2204,7 @@ PreservedAnalyses CoroSplitPass::run(LazyCallGraph::SCC &C,
   if (Coroutines.empty() && PrepareFns.empty())
     return PreservedAnalyses::all();

+  auto *CurrentSCC = &C;
   // Split all the coroutines.
   for (LazyCallGraph::Node *N : Coroutines) {
     Function &F = N->getFunction();
@@ -2211,7 +2216,8 @@ PreservedAnalyses CoroSplitPass::run(LazyCallGraph::SCC &C,
     coro::Shape Shape =
         splitCoroutine(F, Clones, FAM.getResult<TargetIRAnalysis>(F),
                        OptimizeFrame, MaterializableCallback);
-    updateCallGraphAfterCoroutineSplit(*N, Shape, Clones, C, CG, AM, UR, FAM);
+    CurrentSCC = &updateCallGraphAfterCoroutineSplit(
+        *N, Shape, Clones, *CurrentSCC, CG, AM, UR, FAM);

     auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
     ORE.emit([&]() {
@@ -2223,14 +2229,14 @@ PreservedAnalyses CoroSplitPass::run(LazyCallGraph::SCC &C,

     if (!Shape.CoroSuspends.empty()) {
       // Run the CGSCC pipeline on the original and newly split functions.
-      UR.CWorklist.insert(&C);
+      UR.CWorklist.insert(CurrentSCC);
       for (Function *Clone : Clones)
         UR.CWorklist.insert(CG.lookupSCC(CG.get(*Clone)));
     }
   }

   for (auto *PrepareFn : PrepareFns) {
-    replaceAllPrepares(PrepareFn, CG, C);
+    replaceAllPrepares(PrepareFn, CG, *CurrentSCC);
   }

   return PreservedAnalyses::none();

; Verify that we don't crash on mutually recursive coroutines

target triple = "x86_64-redhat-linux-gnu"

define void @foo() presplitcoroutine personality ptr null {
entry:

  %0 = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
  %1 = call ptr @llvm.coro.begin(token %0, ptr null)
  %2 = call token @llvm.coro.save(ptr null)
  %3 = call i8 @llvm.coro.suspend(token none, i1 false)
  %4 = call token @llvm.coro.save(ptr null)
  call void @llvm.coro.await.suspend.void(ptr null, ptr null, ptr @bar)
  ret void
}

define void @bar(ptr %0, ptr %1) {
entry:
  call void @foo()
  ret void
}

declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #0
declare ptr @llvm.coro.begin(token, ptr writeonly) nounwind
declare token @llvm.coro.save(ptr) nomerge nounwind
declare void @llvm.coro.await.suspend.void(ptr, ptr, ptr)
declare i8 @llvm.coro.suspend(token, i1) nounwind

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

"Invalidated the current SCC" assertion failure after #79712

For the source file in https://gist.github.com/smeenai/fcd14380467e813a28f1ef8c5484b775 (reduced from a large example that uses libunifex; it's probably possible to reduce this further but I'm not at all familiar with coroutines), the following command succeeds with Clang 18 but fails with Clang 19 and trunk:

```
$ clang -c -o /dev/null coroutine_crash.cpp -std=c++20 -w
clang: llvm/lib/Analysis/CGSCCPassManager.cpp:1167: LazyCallGraph::SCC &updateCGAndAnalysisManagerForPass(llvm::LazyCallGraph &, LazyCallGraph::SCC &, LazyCallGraph::Node &, llvm::CGSCCAnalysisManager &, llvm::CGSCCUpdateResult &, llvm::FunctionAnalysisManager &, bool): Assertion `!UR.InvalidatedSCCs.count(C) && "Invalidated the current SCC!"' failed.
```

I bisected this to #79712. CC @fpasserby, @ChuanqiXu9, and @yuxuanchen1997

I took a look at this and I think it was due to incorrect call graph updates. `updateCGAndAnalysisManagerFor(CGSCC|Function)Pass` seems to return an updated SCC but we discarded the updated SCC.

See example usage: https://github.com/llvm/llvm-project/blob/main/llvm/lib/Analysis/CGSCCPassManager.cpp#L561-L562
See implementation: https://github.com/llvm/llvm-project/blob/main/llvm/lib/Analysis/CGSCCPassManager.cpp#L1170-L1175

I have a patch https://github.com/llvm/llvm-project/pull/107935 but still need some time for a test case.

This happens when foo has is not a single node SCC:
```
define void @foo() presplitcoroutine personality ptr null {
entry:
  %0 = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
  %1 = call ptr @llvm.coro.begin(token %0, ptr null)
  %2 = call token @llvm.coro.save(ptr null)
  %3 = call i8 @llvm.coro.suspend(token none, i1 false)
  %4 = call token @llvm.coro.save(ptr null)
  call void @llvm.coro.await.suspend.void(ptr null, ptr null, ptr @bar)
  ret void
}

define void @bar(ptr %0, ptr %1) {
entry:
  call void @foo()
  ret void
}

declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #0
declare ptr @llvm.coro.begin(token, ptr writeonly) nounwind
declare token @llvm.coro.save(ptr) nomerge nounwind
declare void @llvm.coro.await.suspend.void(ptr, ptr, ptr)
declare i8 @llvm.coro.suspend(token, i1) nounwind

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

Repro the crash with `clang -O0 bad.ll`.

The 3rd argument to `@llvm.coro.await.suspend` is the `await_suspend` function in C++. This happens when `await_suspend()` calls the same coroutine from its body.


commit 6261c53c6f9c82bfca5df2ed5917876d748ed079
Author: Florian Hahn <flo@fhahn.com>
Date:   Tue Apr 2 21:48:35 2024 +0100

    [VPlan] Make sure OR VPInstructions are treated as disjoint ops.

    Make sure that VPInstructions with OR opcodes are properly registered as
    disjoint ops.

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

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h
index 5d03b66b0ce3..ebca2d855a46 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h
@@ -175,7 +175,10 @@ public:

   VPValue *createOr(VPValue *LHS, VPValue *RHS, DebugLoc DL = {},
                     const Twine &Name = "") {
-    return createInstruction(Instruction::BinaryOps::Or, {LHS, RHS}, DL, Name);
+
+    return tryInsertInstruction(new VPInstruction(
+        Instruction::BinaryOps::Or, {LHS, RHS},
+        VPRecipeWithIRFlags::DisjointFlagsTy(false), DL, Name));
   }

   VPValue *createSelect(VPValue *Cond, VPValue *TrueVal, VPValue *FalseVal,
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h
index 3baca43f7276..707a826ecdc2 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.h
+++ b/llvm/lib/Transforms/Vectorize/VPlan.h
@@ -913,6 +913,11 @@ public:
     WrapFlagsTy(bool HasNUW, bool HasNSW) : HasNUW(HasNUW), HasNSW(HasNSW) {}
   };

+  struct DisjointFlagsTy {
+    char IsDisjoint : 1;
+    DisjointFlagsTy(bool IsDisjoint) : IsDisjoint(IsDisjoint) {}
+  };
+
 protected:
   struct GEPFlagsTy {
     char IsInBounds : 1;
@@ -920,9 +925,6 @@ protected:
   };

 private:
-  struct DisjointFlagsTy {
-    char IsDisjoint : 1;
-  };
   struct ExactFlagsTy {
     char IsExact : 1;
   };
@@ -1016,6 +1018,12 @@ public:
       : VPSingleDefRecipe(SC, Operands, DL), OpType(OperationType::FPMathOp),
         FMFs(FMFs) {}

+  template <typename IterT>
+  VPRecipeWithIRFlags(const unsigned char SC, IterT Operands,
+                      DisjointFlagsTy DisjointFlags, DebugLoc DL = {})
+      : VPSingleDefRecipe(SC, Operands, DL), OpType(OperationType::DisjointOp),
+        DisjointFlags(DisjointFlags) {}
+
 protected:
   template <typename IterT>
   VPRecipeWithIRFlags(const unsigned char SC, IterT Operands,
@@ -1221,6 +1229,14 @@ public:
       : VPRecipeWithIRFlags(VPDef::VPInstructionSC, Operands, WrapFlags, DL),
         Opcode(Opcode), Name(Name.str()) {}

+  VPInstruction(unsigned Opcode, std::initializer_list<VPValue *> Operands,
+                DisjointFlagsTy DisjointFlag, DebugLoc DL = {},
+                const Twine &Name = "")
+      : VPRecipeWithIRFlags(VPDef::VPInstructionSC, Operands, DisjointFlag, DL),
+        Opcode(Opcode), Name(Name.str()) {
+    assert(Opcode == Instruction::Or && "only OR opcodes can be disjoint");
+  }
+
   VPInstruction(unsigned Opcode, std::initializer_list<VPValue *> Operands,
                 FastMathFlags FMFs, DebugLoc DL = {}, const Twine &Name = "");

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

; Test case for https://github.com/llvm/llvm-project/issues/87378.
define void @pr87378_vpinstruction_or_drop_poison_generating_flags(ptr %arg, i64 %a, i64 %b, i64 %c) {
;
entry:
  br label %loop.header

loop.header:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %c.1 = icmp ule i64 %iv, %a
  br i1 %c.1, label %then.1, label %else.1

then.1:
  %c.2 = icmp ule i64 %iv, %b
  br i1 %c.2, label %else.1, label %merge

else.1:
  %c.3 = icmp ule i64 %iv, %c
  br i1 %c.3, label %then.2, label %loop.latch

then.2:
  br label %merge

merge:
  %idx = phi i64 [ poison, %then.1 ], [ %iv, %then.2 ]
  %getelementptr = getelementptr i16, ptr %arg, i64 %idx
  store i16 0, ptr %getelementptr, align 2
  br label %loop.latch

loop.latch:
  %iv.next = add i64 %iv, 1
  %icmp = icmp eq i64 %iv, 1000
  br i1 %icmp, label %exit, label %loop.header

exit:
  ret void
}
;.
;.

[LoopVectorize] Assertion `OpType == OperationType::DisjointOp && "recipe cannot have a disjoing flag"' failed.

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

define i32 @main() #0 {
entry:
  br label %for.body300.us.us.i

for.body300.us.us.i:                              ; preds = %if.end559.us.us.i, %entry
  br label %for.body326.us.us.i

for.body326.us.us.i:                              ; preds = %if.end559.us.us.i, %for.body300.us.us.i
  %indvars.iv18 = phi i64 [ 0, %for.body300.us.us.i ], [ %indvars.iv.next19, %if.end559.us.us.i ]
  br i1 false, label %cond.end339.us.us.i, label %cond.end354.us.us.i

cond.end339.us.us.i:                              ; preds = %for.body326.us.us.i
  br i1 false, label %cond.end339.us.us.i.if.then357.us.us.i_crit_edge, label %cond.end339.us.us.i.cond.end354.us.us.i_crit_edge

cond.end339.us.us.i.cond.end354.us.us.i_crit_edge: ; preds = %cond.end339.us.us.i
  br label %cond.end354.us.us.i

cond.end339.us.us.i.if.then357.us.us.i_crit_edge: ; preds = %cond.end339.us.us.i
  br label %if.then357.us.us.i

cond.end354.us.us.i:                              ; preds = %cond.end339.us.us.i.cond.end354.us.us.i_crit_edge, %for.body326.us.us.i
  br i1 false, label %cond.end354.us.us.i.if.then357.us.us.i_crit_edge, label %if.end559.us.us.i

cond.end354.us.us.i.if.then357.us.us.i_crit_edge: ; preds = %cond.end354.us.us.i
  br label %if.then357.us.us.i

if.then357.us.us.i:                               ; preds = %cond.end354.us.us.i.if.then357.us.us.i_crit_edge, %cond.end339.us.us.i.if.then357.us.us.i_crit_edge
  %.pre1143.i7 = phi i64 [ poison, %cond.end339.us.us.i.if.then357.us.us.i_crit_edge ], [ %indvars.iv18, %cond.end354.us.us.i.if.then357.us.us.i_crit_edge ]
  %arrayidx429.us.us.i = getelementptr [14 x i16], ptr null, i64 0, i64 %.pre1143.i7
  store i16 0, ptr %arrayidx429.us.us.i, align 2
  br label %if.end559.us.us.i

if.end559.us.us.i:                                ; preds = %if.then357.us.us.i, %cond.end354.us.us.i
  %indvars.iv.next19 = add i64 %indvars.iv18, 1
  %0 = trunc i64 %indvars.iv18 to i32
  %cmp323.us.us.i = icmp slt i32 %0, 1
  br i1 %cmp323.us.us.i, label %for.body326.us.us.i, label %for.body300.us.us.i
}

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

Backtrace:
```
opt: /scratch/tc-testing/tc-apr-2/llvm/llvm/lib/Transforms/Vectorize/VPlan.h:1131: bool llvm::VPRecipeWithIRFlags::isDisjoint() const: Assertion `OpType == OperationType::DisjointOp && "recipe cannot have a disjoing flag"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: /scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt reduced.ll --passes=loop-vectorize
 #0 0x00005bd204995b60 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x2d84b60)
 #1 0x00005bd204992f6f llvm::sys::RunSignalHandlers() (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x2d81f6f)
 #2 0x00005bd2049930c5 SignalHandler(int) Signals.cpp:0:0
 #3 0x000076eef1a42520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #4 0x000076eef1a969fc __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #5 0x000076eef1a969fc __pthread_kill_internal ./nptl/pthread_kill.c:78:10
 #6 0x000076eef1a969fc pthread_kill ./nptl/pthread_kill.c:89:10
 #7 0x000076eef1a42476 gsignal ./signal/../sysdeps/posix/raise.c:27:6
 #8 0x000076eef1a287f3 abort ./stdlib/abort.c:81:7
 #9 0x000076eef1a2871b _nl_load_domain ./intl/loadmsgcat.c:1177:9
#10 0x000076eef1a39e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
#11 0x00005bd203b25ea2 llvm::VPlanTransforms::dropPoisonGeneratingRecipes(llvm::VPlan&, llvm::function_ref<bool (llvm::BasicBlock*)>)::'lambda'(llvm::VPRecipeBase*)::operator()(llvm::VPRecipeBase*) const VPlanTransforms.cpp:0:0
#12 0x00005bd203b2c77d llvm::VPlanTransforms::dropPoisonGeneratingRecipes(llvm::VPlan&, llvm::function_ref<bool (llvm::BasicBlock*)>) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x1f1b77d)
#13 0x00005bd203a05435 llvm::LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(llvm::VFRange&) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x1df4435)
#14 0x00005bd203a05c9e llvm::LoopVectorizationPlanner::buildVPlansWithVPRecipes(llvm::ElementCount, llvm::ElementCount) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x1df4c9e)
#15 0x00005bd203a0c319 llvm::LoopVectorizationPlanner::plan(llvm::ElementCount, unsigned int) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x1dfb319)
#16 0x00005bd203a0f8a9 llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x1dfe8a9)
#17 0x00005bd203a1273e llvm::LoopVectorizePass::runImpl(llvm::Function&, llvm::ScalarEvolution&, llvm::LoopInfo&, llvm::TargetTransformInfo&, llvm::DominatorTree&, llvm::BlockFrequencyInfo*, llvm::TargetLibraryInfo*, llvm::DemandedBits&, llvm::AssumptionCache&, llvm::LoopAccessInfoManager&, llvm::OptimizationRemarkEmitter&, llvm::ProfileSummaryInfo*) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x1e0173e)
#18 0x00005bd203a1388d llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x1e0288d)
#19 0x00005bd20291a276 llvm::detail::PassModel<llvm::Function, llvm::LoopVectorizePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0xd09276)
#20 0x00005bd2047bc141 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x2bab141)
#21 0x00005bd202911bd6 llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0xd00bd6)
#22 0x00005bd2047bae3b llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x2ba9e3b)
#23 0x00005bd202919dc6 llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0xd08dc6)
#24 0x00005bd2047b8cb1 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x2ba7cb1)
#25 0x00005bd202193ce5 llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::ArrayRef<std::function<void (llvm::PassBuilder&)>>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x582ce5)
#26 0x00005bd202186316 optMain (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x575316)
#27 0x000076eef1a29d90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#28 0x000076eef1a29e40 call_init ./csu/../csu/libc-start.c:128:20
#29 0x000076eef1a29e40 __libc_start_main ./csu/../csu/libc-start.c:379:5
#30 0x00005bd20217bf95 _start (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x56af95)
zsh: IOT instruction (core dumped)  /scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt reduced.l
```

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

Minor spelling nit: `disjoing -> disjoint`

Found via fuzzer.

Likely caused/exposed by https://github.com/llvm/llvm-project/commit/6ef829941b38f7e8a28c4cba1ff25cd0ae9f7d3d https://github.com/llvm/llvm-project/pull/83821 @fhahn


commit 9e03920cbf946e7ba282e99213707643a23ae5fb
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Mon Oct 21 08:57:36 2024 -0700

    [SLP]Ignore root gather node, when searching for reuses

    Root gather/buildvector node should be ignored when SLP vectorizer tries
    to find matching gather nodes, vectorized earlier. This node is
    definitely the last one in the pipeline and it does not have users. It
    may cause the compiler crash

    Fixes #113143

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 1098bf578d2d..a11e3f3815cb 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -12466,7 +12466,7 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry(
     // Build a list of tree entries where V is used.
     SmallPtrSet<const TreeEntry *, 4> VToTEs;
     for (const TreeEntry *TEPtr : ValueToGatherNodes.find(V)->second) {
-      if (TEPtr == TE)
+      if (TEPtr == TE || TEPtr->Idx == 0)
         continue;
       assert(any_of(TEPtr->Scalars,
                     [&](Value *V) { return GatheredScalars.contains(V); }) &&

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

define void @test(ptr %a, i32 %0, i32 %1, i1 %cmp1) {
entry:
  %2 = load i32, ptr %a, align 4
  %tobool10.not = icmp eq i32 %0, 0
  %cmp4.3 = icmp ne i32 %1, 0
  %3 = and i1 %cmp4.3, %tobool10.not
  %cmp2.2 = xor i1 %tobool10.not, true
  %conv3.2 = zext i1 %cmp2.2 to i32
  %cmp4.2 = icmp ne i32 %2, %conv3.2
  %cmp2.1 = xor i1 %cmp1, true
  %conv3.1 = zext i1 %cmp2.1 to i32
  %cmp4.1 = icmp ne i32 %2, %conv3.1
  %4 = select i1 %3, i1 %cmp4.2, i1 false
  %5 = select i1 %4, i1 %cmp4.1, i1 false
  %and.3 = zext i1 %5 to i32
  store i32 %and.3, ptr %a, align 4
  ret void
}

clang crashes on valid code at -O2 on x86_64-linux-gnu: Assertion `TEPtr->UserTreeIndices.size() == 1 && "Expected only single user of a gather node."' failed

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

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

```
[523] % clangtk -v
clang version 20.0.0git (https://github.com/llvm/llvm-project.git df8b785838a2db01b4d056e603f7317209accefb)
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
[524] %
[524] % clangtk -O2 small.c
clang-20: /local/suz-local/software/clangbuild/llvm-project/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp:12559: std::optional<llvm::TargetTransformInfo::ShuffleKind> llvm::slpvectorizer::BoUpSLP::isGatherShuffledSingleRegisterEntry(const llvm::slpvectorizer::BoUpSLP::TreeEntry*, llvm::ArrayRef<llvm::Value*>, llvm::MutableArrayRef<int>, llvm::SmallVectorImpl<const llvm::slpvectorizer::BoUpSLP::TreeEntry*>&, unsigned int, bool): Assertion `TEPtr->UserTreeIndices.size() == 1 && "Expected only single user of a gather node."' 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/20241020-clangtk-m64-O2-build-231331/delta -fcoverage-compilation-dir=/local/suz-local/software/emitesting/bugs/20241020-clangtk-m64-O2-build-231331/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-572b89.o -x c small.c
1.	<eof> parser at end of file
2.	Optimizer
3.	Running pass "function<eager-inv>(float2int,lower-constant-intrinsics,loop(loop-rotate<header-duplication;no-prepare-for-lto>,loop-deletion),loop-distribute,inject-tli-mappings,loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>,infer-alignment,loop-load-elim,instcombine<max-iterations=1;no-verify-fixpoint>,simplifycfg<bonus-inst-threshold=1;forward-switch-cond;switch-range-to-icmp;switch-to-lookup;no-keep-loops;hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,slp-vectorizer,vector-combine,instcombine<max-iterations=1;no-verify-fixpoint>,loop-unroll<O2>,transform-warning,sroa<preserve-cfg>,infer-alignment,instcombine<max-iterations=1;no-verify-fixpoint>,loop-mssa(licm<allowspeculation>),alignment-from-assumptions,loop-sink,instsimplify,div-rem-pairs,tailcallelim,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;speculate-unpredictables>)" on module "small.c"
4.	Running pass "slp-vectorizer" on function "main"
 #0 0x0000560576c8b9af llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x43f29af)
 #1 0x0000560576c89184 SignalHandler(int) Signals.cpp:0:0
 #2 0x00007f4623c27420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420)
 #3 0x00007f462365e00b raise /build/glibc-LcI20x/glibc-2.31/signal/../sysdeps/unix/sysv/linux/raise.c:51:1
 #4 0x00007f462363d859 abort /build/glibc-LcI20x/glibc-2.31/stdlib/abort.c:81:7
 #5 0x00007f462363d729 get_sysdep_segment_value /build/glibc-LcI20x/glibc-2.31/intl/loadmsgcat.c:509:8
 #6 0x00007f462363d729 _nl_load_domain /build/glibc-LcI20x/glibc-2.31/intl/loadmsgcat.c:970:34
 #7 0x00007f462364efd6 (/lib/x86_64-linux-gnu/libc.so.6+0x33fd6)
 #8 0x0000560578707edc llvm::slpvectorizer::BoUpSLP::isGatherShuffledSingleRegisterEntry(llvm::slpvectorizer::BoUpSLP::TreeEntry const*, llvm::ArrayRef<llvm::Value*>, llvm::MutableArrayRef<int>, llvm::SmallVectorImpl<llvm::slpvectorizer::BoUpSLP::TreeEntry const*>&, unsigned int, bool) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5e6eedc)
 #9 0x0000560578708cd8 llvm::slpvectorizer::BoUpSLP::isGatherShuffledEntry(llvm::slpvectorizer::BoUpSLP::TreeEntry const*, llvm::ArrayRef<llvm::Value*>, llvm::SmallVectorImpl<int>&, llvm::SmallVectorImpl<llvm::SmallVector<llvm::slpvectorizer::BoUpSLP::TreeEntry const*, 6u>>&, unsigned int, bool) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5e6fcd8)
#10 0x000056057870a6f3 llvm::InstructionCost llvm::slpvectorizer::BoUpSLP::processBuildVector<llvm::slpvectorizer::BoUpSLP::ShuffleCostEstimator, llvm::InstructionCost, llvm::TargetTransformInfo, llvm::ArrayRef<llvm::Value*>, llvm::slpvectorizer::BoUpSLP, llvm::SmallPtrSetImpl<llvm::Value*>>(llvm::slpvectorizer::BoUpSLP::TreeEntry const*, llvm::Type*, llvm::TargetTransformInfo&, llvm::ArrayRef<llvm::Value*>&, llvm::slpvectorizer::BoUpSLP&, llvm::SmallPtrSetImpl<llvm::Value*>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5e716f3)
#11 0x000056057870cde7 llvm::slpvectorizer::BoUpSLP::getEntryCost(llvm::slpvectorizer::BoUpSLP::TreeEntry const*, llvm::ArrayRef<llvm::Value*>, llvm::SmallPtrSetImpl<llvm::Value*>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5e73de7)
#12 0x0000560578745f69 llvm::slpvectorizer::BoUpSLP::getTreeCost(llvm::ArrayRef<llvm::Value*>) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5eacf69)
#13 0x000056057874b57b (anonymous namespace)::HorizontalReduction::tryToReduce(llvm::slpvectorizer::BoUpSLP&, llvm::DataLayout const&, llvm::TargetTransformInfo*, llvm::TargetLibraryInfo const&) SLPVectorizer.cpp:0:0
#14 0x000056057874eb79 llvm::SLPVectorizerPass::vectorizeHorReduction(llvm::PHINode*, llvm::Instruction*, llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&, llvm::SmallVectorImpl<llvm::WeakTrackingVH>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5eb5b79)
#15 0x000056057875349b llvm::SLPVectorizerPass::vectorizeRootInstruction(llvm::PHINode*, llvm::Instruction*, llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&) (.constprop.0) SLPVectorizer.cpp:0:0
#16 0x0000560578757d50 llvm::SLPVectorizerPass::vectorizeChainsInBlock(llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5ebed50)
#17 0x000056057875e590 llvm::SLPVectorizerPass::runImpl(llvm::Function&, llvm::ScalarEvolution*, llvm::TargetTransformInfo*, llvm::TargetLibraryInfo*, llvm::AAResults*, llvm::LoopInfo*, llvm::DominatorTree*, llvm::AssumptionCache*, llvm::DemandedBits*, llvm::OptimizationRemarkEmitter*) (.part.0) SLPVectorizer.cpp:0:0
#18 0x000056057875f263 llvm::SLPVectorizerPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5ec6263)
#19 0x00005605781e0e66 llvm::detail::PassModel<llvm::Function, llvm::SLPVectorizerPass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5947e66)
#20 0x0000560576614891 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+0x3d7b891)
#21 0x000056057410e656 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+0x1875656)
#22 0x00005605766131fd llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x3d7a1fd)
#23 0x000056057410d196 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+0x1874196)
#24 0x0000560576612c31 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+0x3d79c31)
#25 0x0000560576f44dd3 (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
#26 0x0000560576f483a8 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+0x46af3a8)
#27 0x000056057764462c clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4dab62c)
#28 0x000056057951629c clang::ParseAST(clang::Sema&, bool, bool) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x6c7d29c)
#29 0x0000560577644a48 clang::CodeGenAction::ExecuteAction() (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4daba48)
#30 0x000056057790d3d9 clang::FrontendAction::Execute() (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x50743d9)
#31 0x00005605778895ce clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x4ff05ce)
#32 0x00005605779f9f26 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x5160f26)
#33 0x0000560573cd1fe5 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x1438fe5)
#34 0x0000560573cc9afa ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#35 0x0000560573cce52e clang_main(int, char**, llvm::ToolContext const&) (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x143552e)
#36 0x0000560573bba67b main (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x132167b)
#37 0x00007f462363f083 __libc_start_main /build/glibc-LcI20x/glibc-2.31/csu/../csu/libc-start.c:342:3
#38 0x0000560573cc958e _start (/local/suz-local/software/local/clang-trunk/bin/clang-20+0x143058e)
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 df8b785838a2db01b4d056e603f7317209accefb)
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-d99d4e.c
clangtk: note: diagnostic msg: /tmp/small-d99d4e.sh
clangtk: note: diagnostic msg:

********************
[525] %
[525] % cat small.c
int a, b, c, d, e, f;
int main() {
  for (f = 0; f < 4; f++) {
    d &= (((a > 0) != b) != c) && b;
    for (b = 0; b < 1; b++)
      if (e)
        break;
  }
  return 0;
}
```