commit a42aa8f265372a15d31a2af10b548fc239ed4b51
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Tue Dec 10 09:19:48 2024 -0800

    [SLP]Fix adjusting of the mask for the fully matched nodes.

    When checking for the poison elements in the matches node, need to
    consider the register number, when clearing the corresponding mask
    element.

    Fixes #119393

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index c729c6cc9195..d90d7cc8f29e 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -13222,9 +13222,9 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry(
         copy(CommonMask, Mask.begin());
       }
       // Clear undef scalars.
-      for (int I = 0, Sz = VL.size(); I < Sz; ++I)
+      for (unsigned I : seq<unsigned>(VL.size()))
         if (isa<PoisonValue>(VL[I]))
-          Mask[I] = PoisonMaskElem;
+          Mask[Part * VL.size() + I] = PoisonMaskElem;
       return TargetTransformInfo::SK_PermuteSingleSrc;
     }
     // No perfect match, just shuffle, so choose the first tree node from the

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

[SLPVectorizer] Assertion `I1 == PoisonMaskElem && "Expected unused subvectors mask"' failed.

Reproducer: https://godbolt.org/z/3dahr6Mb4
```
; bin/opt -passes=slp-vectorizer reduced.ll -S
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

define i32 @main() {
entry:
  br label %func_135.exit.i

func_135.exit.i:
  %g_228.promoted166.i1105.i = phi i32 [ 0, %entry ]
  %cmp55.i.i1199.i = icmp ugt i32 %g_228.promoted166.i1105.i, 0
  %cmp55.1.i.i1200.i = icmp ugt i32 %g_228.promoted166.i1105.i, 0
  %cmp55.2.i.i1201.i = icmp ugt i32 %g_228.promoted166.i1105.i, 0
  %cmp55.3.i.i1202.i = icmp ugt i32 %g_228.promoted166.i1105.i, 0
  %0 = xor i1 %cmp55.2.i.i1201.i, %cmp55.3.i.i1202.i
  %1 = xor i1 %cmp55.1.i.i1200.i, %0
  %2 = xor i1 %cmp55.i.i1199.i, %1
  %dec.i.i1204.i = add i32 %g_228.promoted166.i1105.i, 0
  %cmp55.i.i1199.1.i = icmp ugt i32 %dec.i.i1204.i, 0
  %cmp55.1.i.i1200.1.i = icmp ugt i32 %dec.i.i1204.i, 0
  %cmp55.2.i.i1201.1.i = icmp ugt i32 %dec.i.i1204.i, 0
  %cmp55.3.i.i1202.1.i = icmp ugt i32 %dec.i.i1204.i, 0
  %3 = xor i1 %cmp55.2.i.i1201.1.i, %cmp55.3.i.i1202.1.i
  %4 = xor i1 %cmp55.1.i.i1200.1.i, %3
  %5 = xor i1 %cmp55.i.i1199.1.i, %4
  %6 = xor i1 %2, %5
  %dec.i.i1204.1.i = add i32 %g_228.promoted166.i1105.i, 0
  %cmp55.i.i1199.2.i = icmp ugt i32 %dec.i.i1204.1.i, 0
  %cmp55.1.i.i1200.2.i = icmp ugt i32 %dec.i.i1204.1.i, 0
  %cmp55.2.i.i1201.2.i = icmp ugt i32 %dec.i.i1204.1.i, 0
  %cmp55.3.i.i1202.2.i = icmp ugt i32 %dec.i.i1204.1.i, 0
  %7 = add i32 0, 0
  %8 = icmp ult i32 %7, 0
  %9 = xor i1 %cmp55.3.i.i1202.2.i, %8
  %10 = xor i1 %cmp55.2.i.i1201.2.i, %9
  %11 = xor i1 %cmp55.1.i.i1200.2.i, %10
  %12 = xor i1 %cmp55.i.i1199.2.i, %11
  %13 = xor i1 %12, %6
  %dec.i.i1204.2.i = add i32 %g_228.promoted166.i1105.i, 0
  %cmp55.i.i1199.3.i = icmp ugt i32 %dec.i.i1204.2.i, 0
  %cmp55.1.i.i1200.3.i = icmp ugt i32 %dec.i.i1204.2.i, 0
  %cmp55.2.i.i1201.3.i = icmp ugt i32 %dec.i.i1204.2.i, 0
  %14 = xor i1 %cmp55.1.i.i1200.3.i, %cmp55.2.i.i1201.3.i
  %15 = xor i1 %cmp55.i.i1199.3.i, %14
  %16 = xor i1 %15, %13
  %17 = zext i1 %16 to i16
  br label %if.then.sink.split.i

for.cond7.preheader.i1132.1.i:                    ; No predecessors!
  br label %if.then.sink.split.i

if.then.sink.split.i:                             ; preds = %for.cond7.preheader.i1132.1.i, %func_135.exit.i
  %xor58.5.i.i1203.3.3.sink.i = phi i16 [ 0, %for.cond7.preheader.i1132.1.i ], [ %17, %func_135.exit.i ]
  ret i32 0
}
```
```
opt: /root/llvm-project/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp:10913: llvm::InstructionCost llvm::slpvectorizer::BoUpSLP::ShuffleCostEstimator::finalize(llvm::ArrayRef<int>, llvm::ArrayRef<std::pair<const llvm::slpvectorizer::BoUpSLP::TreeEntry*, unsigned int> >, llvm::ArrayRef<int>, unsigned int, llvm::function_ref<void(llvm::Value*&, llvm::SmallVectorImpl<int>&)>): Assertion `I1 == PoisonMaskElem && "Expected unused subvectors mask"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/opt -o /app/output.s -S -passes=slp-vectorizer <source>
1.	Running pass "function(slp-vectorizer)" on module "<source>"
2.	Running pass "slp-vectorizer" on function "main"
 #0 0x00000000051c9e58 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x51c9e58)
 #1 0x00000000051c785c SignalHandler(int) Signals.cpp:0:0
 #2 0x000078cea7e42520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x000078cea7e969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x000078cea7e42476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x000078cea7e287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x000078cea7e2871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
 #7 0x000078cea7e39e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
 #8 0x00000000041fda54 llvm::slpvectorizer::BoUpSLP::ShuffleCostEstimator::finalize(llvm::ArrayRef<int>, llvm::ArrayRef<std::pair<llvm::slpvectorizer::BoUpSLP::TreeEntry const*, unsigned int>>, llvm::ArrayRef<int>, unsigned int, llvm::function_ref<void (llvm::Value*&, llvm::SmallVectorImpl<int>&)>) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x41fda54)
 #9 0x00000000042390b0 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*>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x42390b0)
#10 0x0000000004243fa7 llvm::slpvectorizer::BoUpSLP::getEntryCost(llvm::slpvectorizer::BoUpSLP::TreeEntry const*, llvm::ArrayRef<llvm::Value*>, llvm::SmallPtrSetImpl<llvm::Value*>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4243fa7)
#11 0x0000000004277f91 llvm::slpvectorizer::BoUpSLP::getTreeCost(llvm::ArrayRef<llvm::Value*>) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4277f91)
#12 0x000000000427da60 (anonymous namespace)::HorizontalReduction::tryToReduce(llvm::slpvectorizer::BoUpSLP&, llvm::DataLayout const&, llvm::TargetTransformInfo*, llvm::TargetLibraryInfo const&) SLPVectorizer.cpp:0:0
#13 0x0000000004280ea9 llvm::SLPVectorizerPass::vectorizeHorReduction(llvm::PHINode*, llvm::Instruction*, llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&, llvm::SmallVectorImpl<llvm::WeakTrackingVH>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4280ea9)
#14 0x000000000428563b llvm::SLPVectorizerPass::vectorizeRootInstruction(llvm::PHINode*, llvm::Instruction*, llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&) (.constprop.0) SLPVectorizer.cpp:0:0
#15 0x0000000004289c9f llvm::SLPVectorizerPass::vectorizeChainsInBlock(llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4289c9f)
#16 0x0000000004290786 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
#17 0x00000000042912cb llvm::SLPVectorizerPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x42912cb)
#18 0x0000000002fdbfee llvm::detail::PassModel<llvm::Function, llvm::SLPVectorizerPass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x2fdbfee)
#19 0x0000000004fc8d00 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4fc8d00)
#20 0x0000000000e3b51e llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xe3b51e)
#21 0x0000000004fc761b llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4fc761b)
#22 0x0000000000e3abae llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xe3abae)
#23 0x0000000004fc7020 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4fc7020)
#24 0x00000000009177ca 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+0x9177ca)
#25 0x0000000000909e49 optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x909e49)
#26 0x000078cea7e29d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#27 0x000078cea7e29e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#28 0x0000000000901705 _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x901705)
Program terminated with signal: SIGSEGV
Compiler returned: 139
```


commit 6a65e98fa7901dc1de91172d065fafb16ce89d77
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Fri Oct 11 18:19:21 2024 +0800

    [InstCombine] Drop range attributes in `foldIsPowerOf2` (#111946)

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

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 688601a8ffa5..964616a4eb35 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -955,9 +955,11 @@ static Value *foldIsPowerOf2OrZero(ICmpInst *Cmp0, ICmpInst *Cmp1, bool IsAnd,
 }

 /// Reduce a pair of compares that check if a value has exactly 1 bit set.
-/// 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 *foldIsPowerOf2(ICmpInst *Cmp0, ICmpInst *Cmp1, bool JoinedByAnd,
-                             InstCombiner::BuilderTy &Builder) {
+                             InstCombiner::BuilderTy &Builder,
+                             InstCombinerImpl &IC) {
   // Handle 'and' / 'or' commutation: make the equality check the first operand.
   if (JoinedByAnd && Cmp1->getPredicate() == ICmpInst::ICMP_NE)
     std::swap(Cmp0, Cmp1);
@@ -971,7 +973,10 @@ static Value *foldIsPowerOf2(ICmpInst *Cmp0, ICmpInst *Cmp1, bool JoinedByAnd,
       match(Cmp1, m_SpecificICmp(ICmpInst::ICMP_ULT,
                                  m_Intrinsic<Intrinsic::ctpop>(m_Specific(X)),
                                  m_SpecificInt(2)))) {
-    Value *CtPop = Cmp1->getOperand(0);
+    auto *CtPop = cast<Instruction>(Cmp1->getOperand(0));
+    // Drop range attributes and re-infer them in the next iteration.
+    CtPop->dropPoisonGeneratingAnnotations();
+    IC.addToWorklist(CtPop);
     return Builder.CreateICmpEQ(CtPop, ConstantInt::get(CtPop->getType(), 1));
   }
   // (X == 0) || (ctpop(X) u> 1) --> ctpop(X) != 1
@@ -980,7 +985,10 @@ static Value *foldIsPowerOf2(ICmpInst *Cmp0, ICmpInst *Cmp1, bool JoinedByAnd,
       match(Cmp1, m_SpecificICmp(ICmpInst::ICMP_UGT,
                                  m_Intrinsic<Intrinsic::ctpop>(m_Specific(X)),
                                  m_SpecificInt(1)))) {
-    Value *CtPop = Cmp1->getOperand(0);
+    auto *CtPop = cast<Instruction>(Cmp1->getOperand(0));
+    // Drop range attributes and re-infer them in the next iteration.
+    CtPop->dropPoisonGeneratingAnnotations();
+    IC.addToWorklist(CtPop);
     return Builder.CreateICmpNE(CtPop, ConstantInt::get(CtPop->getType(), 1));
   }
   return nullptr;
@@ -3375,7 +3383,7 @@ Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
     if (Value *V = foldSignedTruncationCheck(LHS, RHS, I, Builder))
       return V;

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

   if (Value *V = foldPowerOf2AndShiftedMask(LHS, RHS, IsAnd, Builder))

; 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) }

; 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 <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) }

[InstCombine] poison-generating attributes are not dropped when folding logical and/or of icmps

Reproducer: https://alive2.llvm.org/ce/z/rSUfvo
```
define i1 @src(i32 noundef %Value) {
entry:
  %cmp.not = icmp eq i32 %Value, 0
  %0 = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 %Value)
  %cmp1 = icmp ult i32 %0, 2
  %1 = select i1 %cmp.not, i1 false, i1 %cmp1
  ret i1 %1
}

define i1 @tgt(i32 noundef %Value) {
entry:
  %0 = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 %Value)
  %1 = icmp eq i32 %0, 1
  ret i1 %1
}
```
When `%Value == 0`, `@src` returns `false` but `@tgt` returns `poison`.
This miscompilation was triggered after https://github.com/llvm/llvm-project/pull/111284 was landed.


commit 6f68010f9123aae9f6f105d7a11af22458518ad7
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Wed Dec 18 20:40:33 2024 +0800

    [InstCombine] Drop samesign flags in `foldLogOpOfMaskedICmps_NotAllZeros_BMask_Mixed` (#120373)

    Counterexamples: https://alive2.llvm.org/ce/z/6Ks8Qz
    Closes https://github.com/llvm/llvm-project/issues/120361.

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index dff9304be64d..e576eea4ca36 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -455,14 +455,20 @@ static Value *foldLogOpOfMaskedICmps_NotAllZeros_BMask_Mixed(
   // RHS. For example,
   // (icmp ne (A & 255), 0) & (icmp eq (A & 15), 8) -> (icmp eq (A & 15), 8).
   // (icmp ne (A & 15), 0) & (icmp eq (A & 15), 8) -> (icmp eq (A & 15), 8).
-  if (IsSuperSetOrEqual(BCst, DCst))
+  if (IsSuperSetOrEqual(BCst, DCst)) {
+    // We can't guarantee that samesign hold after this fold.
+    RHS->setSameSign(false);
     return RHS;
+  }
   // Otherwise, B is a subset of D. If B and E have a common bit set,
   // ie. (B & E) != 0, then LHS is subsumed by RHS. For example.
   // (icmp ne (A & 12), 0) & (icmp eq (A & 15), 8) -> (icmp eq (A & 15), 8).
   assert(IsSubSetOrEqual(BCst, DCst) && "Precondition due to above code");
-  if ((*BCst & ECst) != 0)
+  if ((*BCst & ECst) != 0) {
+    // We can't guarantee that samesign hold after this fold.
+    RHS->setSameSign(false);
     return RHS;
+  }
   // Otherwise, LHS and RHS contradict and the whole expression becomes false
   // (or true if negated.) For example,
   // (icmp ne (A & 7), 0) & (icmp eq (A & 15), 8) -> false.

define i1 @pr120361(i8 %x, i8 %y) {
  %cmp1 = icmp samesign eq i8 %x, -1
  %cmp2 = icmp ne i8 %x, 0
  %result = select i1 %cmp2, i1 %cmp1, i1 false
  ret i1 %result
}

define i1 @pr120361_v2(i32 %x) {
  %and1 = and i32 %x, 15
  %cmp1 = icmp ne i32 %and1, 0
  %and2 = and i32 %x, -113
  %cmp2 = icmp samesign eq i32 %and2, 15
  %and = select i1 %cmp1, i1 %cmp2, i1 false
  ret i1 %and
}

define i1 @masked_icmps_bmask_notmixed_not_subset_notoptimized(i32 %A) {
  %mask1 = and i32 %A, 254
  %tst1 = icmp ne i32 %mask1, 252
  %mask2 = and i32 %A, 253
  %tst2 = icmp ne i32 %mask2, 252
  %res = and i1 %tst1, %tst2
  ret i1 %res
}

[InstCombine] `samesign` should be dropped when folding logical and of icmps

Reproducer: https://alive2.llvm.org/ce/z/YSW_NC
```
define i1 @src(i8 %0, i8 %1) {
start:
  %2 = icmp samesign eq i8 %0, -1
  %3 = icmp ne i8 %0, 0
  %4 = icmp ugt i8 %0, %0
  %result = select i1 %3, i1 %2, i1 %4
  ret i1 %result
}

define i1 @tgt(i8 %0, i8 %1) {
start:
  %2 = icmp samesign eq i8 %0, -1
  ret i1 %2
}
```
```

----------------------------------------
define i1 @src(i8 %#0, i8 %#1) {
start:
  %#2 = icmp samesign eq i8 %#0, 255
  %#3 = icmp ne i8 %#0, 0
  %#4 = icmp ugt i8 %#0, %#0
  %result = select i1 %#3, i1 %#2, i1 %#4
  ret i1 %result
}
=>
define i1 @tgt(i8 %#0, i8 %#1) {
start:
  %#2 = icmp samesign eq i8 %#0, 255
  ret i1 %#2
}
Transformation doesn't verify!

ERROR: Target is more poisonous than source

Example:
i8 %#0 = #x00 (0)
i8 %#1 = poison

Source:
i1 %#2 = poison
i1 %#3 = #x0 (0)
i1 %#4 = #x0 (0)
i1 %result = #x0 (0)

Target:
i1 %#2 = poison
Source value: #x0 (0)
Target value: poison
```
Reported by https://github.com/dtcxzyw/llvm-mutation-based-fuzz-service/issues/14 while reviewing https://github.com/llvm/llvm-project/pull/120177.


commit 07efe2c18a63423943a4f9d9daeada23601f84c8
Author: Nikita Popov <npopov@redhat.com>
Date:   Wed Jan 29 09:09:14 2025 +0100

    [SCEV] Check correct value for UB (#124302)

    This is a followup to #117152. That patch introduced a check for
    UB/poison on BEValue. However, the SCEV we're actually going to use is
    Shifted. In some cases, it's possible for Shifted to contain UB, while
    BEValue doesn't.

    In the test case the values are:

    BEValue: (-1 * (zext i8 (-83 + ((-83 /u {1,+,1}<%loop>) *
    {-1,+,-1}<%loop>)) to i32))<nuw><nsw>
    Shifted: (-173 + (-1 * (zext i8 ((-83 /u {0,+,1}<%loop>) *
    {0,+,-1}<%loop>) to i32))<nuw><nsw>)<nuw><nsw>

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

diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 7d7d37b3d228..2ce40877b523 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -5917,20 +5917,18 @@ const SCEV *ScalarEvolution::createAddRecFromPHI(PHINode *PN) {
     //   PHI(f(0), f({1,+,1})) --> f({0,+,1})

     // Do not allow refinement in rewriting of BEValue.
-    if (isGuaranteedNotToCauseUB(BEValue)) {
-      const SCEV *Shifted = SCEVShiftRewriter::rewrite(BEValue, L, *this);
-      const SCEV *Start = SCEVInitRewriter::rewrite(Shifted, L, *this, false);
-      if (Shifted != getCouldNotCompute() && Start != getCouldNotCompute() &&
-          ::impliesPoison(BEValue, Start)) {
-        const SCEV *StartVal = getSCEV(StartValueV);
-        if (Start == StartVal) {
-          // Okay, for the entire analysis of this edge we assumed the PHI
-          // to be symbolic.  We now need to go back and purge all of the
-          // entries for the scalars that use the symbolic expression.
-          forgetMemoizedResults(SymbolicName);
-          insertValueToMap(PN, Shifted);
-          return Shifted;
-        }
+    const SCEV *Shifted = SCEVShiftRewriter::rewrite(BEValue, L, *this);
+    const SCEV *Start = SCEVInitRewriter::rewrite(Shifted, L, *this, false);
+    if (Shifted != getCouldNotCompute() && Start != getCouldNotCompute() &&
+        isGuaranteedNotToCauseUB(Shifted) && ::impliesPoison(Shifted, Start)) {
+      const SCEV *StartVal = getSCEV(StartValueV);
+      if (Start == StartVal) {
+        // Okay, for the entire analysis of this edge we assumed the PHI
+        // to be symbolic.  We now need to go back and purge all of the
+        // entries for the scalars that use the symbolic expression.
+        forgetMemoizedResults(SymbolicName);
+        insertValueToMap(PN, Shifted);
+        return Shifted;
       }
     }
   }

define i32 @src() {
bb:
  br label %bb1

bb1:                                              ; preds = %bb4, %bb
  %phi = phi i32 [ -173, %bb ], [ %sub, %bb4 ]
  %phi2 = phi i32 [ 1, %bb ], [ %add, %bb4 ]
  %srem = srem i32 729259140, %phi
  %trunc = trunc i32 %phi2 to i8
  %urem = urem i8 -83, %trunc
  %zext = zext i8 %urem to i32
  %sub = sub nsw i32 0, %zext
  br label %bb4

bb4:                                              ; preds = %bb1
  %add = add nuw nsw i32 %phi2, 1
  %icmp = icmp eq i32 %sub, 0
  br i1 %icmp, label %bb5, label %bb1

bb5:                                              ; preds = %bb4
  %phi6 = phi i32 [ %srem, %bb4 ]
  ret i32 %phi6
}

[Indvars] Miscompile: SSA value incorrectly simplified

One can find the incorrect transformation here: https://godbolt.org/z/T9qMhT7rb
And the proof of incorrect transformation here: https://alive2.llvm.org/ce/z/PXjb5J

For the record, I describe the problem here. Given the IR:
```
define i32 @widget() {
bb:
  br label %bb1

bb1:                                              ; preds = %bb4, %bb
  %phi = phi i32 [ -173, %bb ], [ %sub, %bb4 ]
  %phi2 = phi i32 [ 1, %bb ], [ %add, %bb4 ]
  %srem = srem i32 729259140, %phi
  %trunc = trunc i32 %phi2 to i8
  %urem = urem i8 -83, %trunc
  %zext = zext i8 %urem to i32
  %sub = sub nsw i32 0, %zext
  br label %bb4

bb4:                                              ; preds = %bb1
  %add = add nuw nsw i32 %phi2, 1
  %icmp = icmp eq i32 %sub, 0
  br i1 %icmp, label %bb5, label %bb1

bb5:                                              ; preds = %bb4
  %phi6 = phi i32 [ %srem, %bb4 ]
  ret i32 %phi6
}
```
which returns `srem i32 729259140, -173` which is `130`. The above IR under the `indvars` pass transforms to:
```
define i32 @widget() {
  br label %bb1

bb1:                                              ; preds = %bb4, %bb
  br label %bb4

bb4:                                              ; preds = %bb1
  br i1 true, label %bb5, label %bb1

bb5:                                              ; preds = %bb4
  ret i32 729259140
}
```
which returns `729259140` which is the wrong answer.

Slightly cleaned up:
```
define i32 @test() {
bb:
  br label %loop

loop:
  %phi = phi i32 [ -173, %bb ], [ %sub, %loop ]
  %iv2 = phi i32 [ 1, %bb ], [ %iv2.inc, %loop ]
  %srem = srem i32 729259140, %phi
  %trunc = trunc i32 %iv2 to i8
  %urem = urem i8 -83, %trunc
  %zext = zext i8 %urem to i32
  %sub = sub i32 0, %zext
  %iv2.inc = add i32 %iv2, 1
  %icmp = icmp eq i32 %zext, 0
  br i1 %icmp, label %exit, label %loop

exit:
  %srem.lcssa = phi i32 [ %srem, %loop ]
  ret i32 %srem.lcssa
}
```

Incorrect exit value is computed by SCEV:
```
  -->  (729259140 + (-1 * (-173 + (-1 * (zext i8 ((-83 /u {0,+,1}<%loop>) * {0,+,-1}<%loop>) to i32))<nuw><nsw>)<nuw><nsw> * (729259140 /u (-173 + (-1 * (zext i8 ((-83 /u {0,+,1}<%loop>) * {0,+,-1}<%loop>) to i32))<nuw><nsw>)<nuw><nsw>)))<nuw><nsw> U: empty-set S: empty-set		Exits: 729259140		LoopDispositions: { %loop: Computable }
```