commit 1e3536ef3141d6429f3616af624b81b6d6ab2959
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Fri Sep 13 15:40:22 2024 -0700

    [SLP]Fix PR108620: Need to check, if the reduced value was transformed

    Before trying to include the scalar into the list of
    ExternallyUsedValues, need to check, if it was transformed in previous
    iteration and use the transformed value, not the original one, to avoid
    compiler crash when building external uses.

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

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 0afe02fc08ff..5f2bf082fb87 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -1283,11 +1283,8 @@ public:
   /// Vectorize the tree but with the list of externally used values \p
   /// ExternallyUsedValues. Values in this MapVector can be replaced but the
   /// generated extractvalue instructions.
-  /// \param ReplacedExternals containd list of replaced external values
-  /// {scalar, replace} after emitting extractelement for external uses.
   Value *
   vectorizeTree(const ExtraValueToDebugLocsMap &ExternallyUsedValues,
-                SmallVectorImpl<std::pair<Value *, Value *>> &ReplacedExternals,
                 Instruction *ReductionRoot = nullptr);

   /// \returns the cost incurred by unwanted spills and fills, caused by
@@ -14222,14 +14219,12 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) {

 Value *BoUpSLP::vectorizeTree() {
   ExtraValueToDebugLocsMap ExternallyUsedValues;
-  SmallVector<std::pair<Value *, Value *>> ReplacedExternals;
-  return vectorizeTree(ExternallyUsedValues, ReplacedExternals);
+  return vectorizeTree(ExternallyUsedValues);
 }

-Value *BoUpSLP::vectorizeTree(
-    const ExtraValueToDebugLocsMap &ExternallyUsedValues,
-    SmallVectorImpl<std::pair<Value *, Value *>> &ReplacedExternals,
-    Instruction *ReductionRoot) {
+Value *
+BoUpSLP::vectorizeTree(const ExtraValueToDebugLocsMap &ExternallyUsedValues,
+                       Instruction *ReductionRoot) {
   // All blocks must be scheduled before any instructions are inserted.
   for (auto &BSIter : BlocksSchedules) {
     scheduleBlock(BSIter.second.get());
@@ -14373,6 +14368,7 @@ Value *BoUpSLP::vectorizeTree(
   SmallDenseSet<Value *, 4> UsedInserts;
   DenseMap<std::pair<Value *, Type *>, Value *> VectorCasts;
   SmallDenseSet<Value *, 4> ScalarsWithNullptrUser;
+  SmallDenseSet<ExtractElementInst *, 4> IgnoredExtracts;
   // Extract all of the elements with the external uses.
   for (const auto &ExternalUse : ExternalUses) {
     Value *Scalar = ExternalUse.Scalar;
@@ -14426,11 +14422,16 @@ Value *BoUpSLP::vectorizeTree(
           if (ReplaceInst) {
             // Leave the instruction as is, if it cheaper extracts and all
             // operands are scalar.
-            auto *CloneInst = Inst->clone();
-            CloneInst->insertBefore(Inst);
-            if (Inst->hasName())
-              CloneInst->takeName(Inst);
-            Ex = CloneInst;
+            if (auto *EE = dyn_cast<ExtractElementInst>(Inst)) {
+              IgnoredExtracts.insert(EE);
+              Ex = EE;
+            } else {
+              auto *CloneInst = Inst->clone();
+              CloneInst->insertBefore(Inst);
+              if (Inst->hasName())
+                CloneInst->takeName(Inst);
+              Ex = CloneInst;
+            }
           } else if (auto *ES = dyn_cast<ExtractElementInst>(Scalar);
                      ES && isa<Instruction>(Vec)) {
             Value *V = ES->getVectorOperand();
@@ -14530,8 +14531,12 @@ Value *BoUpSLP::vectorizeTree(
       }
       Value *NewInst = ExtractAndExtendIfNeeded(Vec);
       // Required to update internally referenced instructions.
-      Scalar->replaceAllUsesWith(NewInst);
-      ReplacedExternals.emplace_back(Scalar, NewInst);
+      if (Scalar != NewInst) {
+        assert((!isa<ExtractElementInst>(Scalar) ||
+                !IgnoredExtracts.contains(cast<ExtractElementInst>(Scalar))) &&
+               "Extractelements should not be replaced.");
+        Scalar->replaceAllUsesWith(NewInst);
+      }
       continue;
     }

@@ -14757,6 +14762,9 @@ Value *BoUpSLP::vectorizeTree(
       if (Entry->getOpcode() == Instruction::GetElementPtr &&
           !isa<GetElementPtrInst>(Scalar))
         continue;
+      if (auto *EE = dyn_cast<ExtractElementInst>(Scalar);
+          EE && IgnoredExtracts.contains(EE))
+        continue;
 #ifndef NDEBUG
       Type *Ty = Scalar->getType();
       if (!Ty->isVoidTy()) {
@@ -17660,7 +17668,6 @@ public:
     // because of the vectorization.
     DenseMap<Value *, WeakTrackingVH> TrackedVals(ReducedVals.size() *
                                                   ReducedVals.front().size());
-    SmallVector<std::pair<Value *, Value *>> ReplacedExternals;

     // The compare instruction of a min/max is the insertion point for new
     // instructions and may be replaced with a new compare instruction.
@@ -17956,6 +17963,8 @@ public:
           if (Cnt >= Pos && Cnt < Pos + ReduxWidth)
             continue;
           Value *RdxVal = Candidates[Cnt];
+          if (auto It = TrackedVals.find(RdxVal); It != TrackedVals.end())
+            RdxVal = It->second;
           if (!Visited.insert(RdxVal).second)
             continue;
           // Check if the scalar was vectorized as part of the vectorization
@@ -18024,8 +18033,8 @@ public:
           InsertPt = GetCmpForMinMaxReduction(RdxRootInst);

         // Vectorize a tree.
-        Value *VectorizedRoot = V.vectorizeTree(LocalExternallyUsedValues,
-                                                ReplacedExternals, InsertPt);
+        Value *VectorizedRoot =
+            V.vectorizeTree(LocalExternallyUsedValues, InsertPt);

         Builder.SetInsertPoint(InsertPt);

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

define void @test(i32 %arg) {
bb:
  br label %bb1

bb1:                                              ; preds = %bb1, %bb
  %phi = phi i32 [ 0, %bb ], [ %add27, %bb1 ]
  %phi2 = phi i32 [ 0, %bb ], [ %add24, %bb1 ]
  %phi3 = phi i32 [ 0, %bb ], [ %xor26, %bb1 ]
  %add = add i32 %phi2, 0
  %add4 = add i32 %phi2, 0
  %xor = xor i32 %add, %add4
  %add5 = add i32 %phi, 0
  %add6 = add i32 %phi2, 0
  %add7 = add i32 %phi2, 0
  %xor8 = xor i32 %add6, %xor
  %xor9 = xor i32 %xor8, %add5
  %xor10 = xor i32 %xor9, %add7
  %add11 = add i32 %phi, 0
  %add12 = add i32 %phi2, 0
  %add13 = add i32 %phi2, 0
  %xor14 = xor i32 %add12, %xor10
  %xor15 = xor i32 %xor14, %add11
  %xor16 = xor i32 %xor15, %add13
  %add17 = add i32 %phi, 0
  %add18 = add i32 %phi2, 0
  %add19 = add i32 %phi2, 0
  %xor20 = xor i32 %add18, %xor16
  %xor21 = xor i32 %xor20, %add17
  %xor22 = xor i32 %xor21, %add19
  %add23 = add i32 %phi2, 0
  %add24 = add i32 %arg, 0
  %xor25 = xor i32 %add23, %xor22
  %xor26 = xor i32 %xor25, %add24
  %add27 = add i32 1, 0
  %icmp = icmp ult i32 %add27, 0
  br label %bb1
}

To reproduce run the following test with -passes=slp-vectorizer
```
; ModuleID = './reduced.ll'
source_filename = "./reduced.ll"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128-ni:1-p2:32:8:8:32-ni:2"
target triple = "x86_64-unknown-linux-gnu"

define void @wombat(i32 %arg) gc "statepoint-example" {
bb:
  br label %bb1

bb1:                                              ; preds = %bb1, %bb
  %phi = phi i32 [ 0, %bb ], [ %add27, %bb1 ]
  %phi2 = phi i32 [ 0, %bb ], [ %add24, %bb1 ]
  %phi3 = phi i32 [ 0, %bb ], [ %xor26, %bb1 ]
  %add = add i32 %phi2, 0
  %add4 = add i32 %phi2, 0
  %xor = xor i32 %add, %add4
  %add5 = add i32 %phi, 0
  %add6 = add i32 %phi2, 0
  %add7 = add i32 %phi2, 0
  %xor8 = xor i32 %add6, %xor
  %xor9 = xor i32 %xor8, %add5
  %xor10 = xor i32 %xor9, %add7
  %add11 = add i32 %phi, 0
  %add12 = add i32 %phi2, 0
  %add13 = add i32 %phi2, 0
  %xor14 = xor i32 %add12, %xor10
  %xor15 = xor i32 %xor14, %add11
  %xor16 = xor i32 %xor15, %add13
  %add17 = add i32 %phi, 0
  %add18 = add i32 %phi2, 0
  %add19 = add i32 %phi2, 0
  %xor20 = xor i32 %add18, %xor16
  %xor21 = xor i32 %xor20, %add17
  %xor22 = xor i32 %xor21, %add19
  %add23 = add i32 %phi2, 0
  %add24 = add i32 %arg, 0
  %xor25 = xor i32 %add23, %xor22
  %xor26 = xor i32 %xor25, %add24
  %add27 = add i32 1, 0
  %icmp = icmp ult i32 %add27, 0
  br label %bb1
}
```
Reproducer: https://godbolt.org/z/77hKre61P

Stack dump:
```
opt: /root/llvm-project/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp:2663: void llvm::slpvectorizer::BoUpSLP::removeInstructionsAndOperands(llvm::ArrayRef<U*>) [with T = llvm::Instruction]: Assertion `(I->use_empty() || all_of(I->uses(), [&](Use &U) { return isDeleted( cast<Instruction>(U.getUser())); })) && "trying to erase instruction with users."' 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 "wombat"
 #0 0x00000000050106b8 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x50106b8)
 #1 0x000000000500ddfc SignalHandler(int) Signals.cpp:0:0
 #2 0x0000737fffa42520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x0000737fffa969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x0000737fffa42476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x0000737fffa287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x0000737fffa2871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
 #7 0x0000737fffa39e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
 #8 0x00000000040b91cf void llvm::slpvectorizer::BoUpSLP::removeInstructionsAndOperands<llvm::Instruction>(llvm::ArrayRef<llvm::Instruction*>) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x40b91cf)
 #9 0x000000000410b80a llvm::slpvectorizer::BoUpSLP::vectorizeTree(llvm::MapVector<llvm::Value*, llvm::SmallVector<llvm::Instruction*, 2u>, llvm::DenseMap<llvm::Value*, unsigned int, llvm::DenseMapInfo<llvm::Value*, void>, llvm::detail::DenseMapPair<llvm::Value*, unsigned int>>, llvm::SmallVector<std::pair<llvm::Value*, llvm::SmallVector<llvm::Instruction*, 2u>>, 0u>> const&, llvm::SmallVectorImpl<std::pair<llvm::Value*, llvm::Value*>>&, llvm::Instruction*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x410b80a)
#10 0x0000000004115bed (anonymous namespace)::HorizontalReduction::tryToReduce(llvm::slpvectorizer::BoUpSLP&, llvm::DataLayout const&, llvm::TargetTransformInfo*, llvm::TargetLibraryInfo const&) SLPVectorizer.cpp:0:0
#11 0x0000000004118321 llvm::SLPVectorizerPass::vectorizeHorReduction(llvm::PHINode*, llvm::Instruction*, llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&, llvm::TargetTransformInfo*, llvm::SmallVectorImpl<llvm::WeakTrackingVH>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4118321)
#12 0x000000000411cb18 llvm::SLPVectorizerPass::vectorizeRootInstruction(llvm::PHINode*, llvm::Instruction*, llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&, llvm::TargetTransformInfo*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x411cb18)
#13 0x00000000041212fa llvm::SLPVectorizerPass::vectorizeChainsInBlock(llvm::BasicBlock*, llvm::slpvectorizer::BoUpSLP&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x41212fa)
#14 0x0000000004127719 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
#15 0x00000000041283cb llvm::SLPVectorizerPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x41283cb)
#16 0x0000000002efda4e 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+0x2efda4e)
#17 0x0000000004e12948 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4e12948)
#18 0x0000000000e06f8e 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+0xe06f8e)
#19 0x0000000004e1136e llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4e1136e)
#20 0x0000000000e0679e 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+0xe0679e)
#21 0x0000000004e10da0 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4e10da0)
#22 0x00000000008fb642 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+0x8fb642)
#23 0x00000000008ee4cc optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8ee4cc)
#24 0x0000737fffa29d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#25 0x0000737fffa29e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#26 0x00000000008e5f9e _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8e5f9e)
Program terminated with signal: SIGSEGV
Compiler returned: 139
```


commit 082c81ae4ab9db6bb0acd52098288223dd58501a
Author: Florian Hahn <flo@fhahn.com>
Date:   Tue May 7 21:31:40 2024 +0100

    [LV] Properly extend versioned constant strides.

    We only version unknown strides to 1. If the original type is i1, then
    the sign of the extension matters. Properly extend the stride value
    before replacing it.

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

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 3be0102bea3e..261933966b74 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -8841,8 +8841,10 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
       VPValue *StrideVPV = Plan->getLiveIn(U);
       if (!StrideVPV)
         continue;
-      VPValue *CI = Plan->getOrAddLiveIn(ConstantInt::get(
-          U->getType(), ScevStride->getAPInt().getSExtValue()));
+      unsigned BW = U->getType()->getScalarSizeInBits();
+      APInt C = isa<SExtInst>(U) ? ScevStride->getAPInt().sext(BW)
+                                 : ScevStride->getAPInt().zext(BW);
+      VPValue *CI = Plan->getOrAddLiveIn(ConstantInt::get(U->getType(), C));
       StrideVPV->replaceAllUsesWith(CI);
     }
   }

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

target datalayout = "p:8:8:8"

; Function Attrs: mustprogress
define void @zext_of_i1_stride(i1 %g, ptr %dst) #0 {
entry:
  %g.16 = zext i1 %g to i16
  %g.64 = zext i1 %g to i64
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %gep = getelementptr inbounds i16, ptr %dst, i64 %iv
  store i16 %g.16, ptr %gep, align 2
  %iv.next = add nuw nsw i64 %iv, %g.64
  %cmp = icmp ult i64 %iv.next, 16
  br i1 %cmp, label %loop, label %exit

exit:                                             ; preds = %loop
  ret void
}

attributes #0 = { mustprogress }

[LoopVectorize] Sign-extension miscompile

C Testcase:
```c
long a, d;
short b[20];
short c[20];
_Bool e[20];
int f(_Bool g) {
  for (long h = 0; h < 16; h += g)
    b[h] = (short) g;
  for (int i = 0; i < 12; i++)
    for (int j = d; j; j++)
      c[i] = (short) a < e[i];
  return (int) b[0];
}
int main() {
  __builtin_printf("%X\n", f(1));
}
```
Godbolt: https://godbolt.org/z/3E8frs1Me

With loop-vectorize: `FFFFFFFF`
Without loop-vectorize: `1`

Reduced LLVM IR:
```llvm ir
; ModuleID = 'red.ll'
source_filename = "red.c"
target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "riscv64-unknown-linux-gnu"

@b = global [20 x i16] zeroinitializer, align 2
@.str = constant [4 x i8] c"%X\0A\00"

; Function Attrs: nofree norecurse nosync nounwind memory(readwrite, argmem: none, inaccessiblemem: none) uwtable vscale_range(2,1024)
define i32 @f(i1 %g) #0 {
entry:
  %conv = zext i1 %g to i16
  %zext.g.i64 = zext i1 %g to i64
  br label %for.body

for.cond3.preheader:                              ; preds = %for.body
  %0 = load i64, ptr @b, align 2
  %zero = and i64 %0, 0
  %true = icmp eq i64 %zero, 0
  %2 = load i16, ptr @b, align 2
  %conv26 = sext i16 %2 to i32
  ret i32 %conv26

for.body:                                         ; preds = %for.body, %entry
  %phi.0 = phi i64 [ 0, %entry ], [ %add, %for.body ]
  %idx.0 = getelementptr inbounds [20 x i16], ptr @b, i64 0, i64 %phi.0
  store i16 %conv, ptr %idx.0, align 2
  %add = add nuw nsw i64 %phi.0, %zext.g.i64
  %cmp = icmp ult i64 %add, 16
  br i1 %cmp, label %for.body, label %for.cond3.preheader, !llvm.loop !0
}

; Function Attrs: nofree nounwind uwtable vscale_range(2,1024)
define noundef signext i32 @main() #1 {
entry:
  %call = tail call signext i32 @f(i1 noundef zeroext true)
  %call1 = tail call signext i32 (ptr, ...) @printf(ptr noundef nonnull @.str, i32 noundef signext %call) #3
  ret i32 0
}

; Function Attrs: nofree nounwind
declare noundef signext i32 @printf(ptr nocapture noundef readonly, ...) #2

attributes #0 = { nofree norecurse nosync nounwind memory(readwrite, argmem: none, inaccessiblemem: none) uwtable vscale_range(2,1024) "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic-rv64" "target-features"="+64bit,+a,+c,+d,+f,+m,+relax,+v,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b,-e,-experimental-smmpm,-experimental-smnpm,-experimental-ssnpm,-experimental-sspm,-experimental-ssqosid,-experimental-supm,-experimental-zaamo,-experimental-zabha,-experimental-zalasr,-experimental-zalrsc,-experimental-zfbfmin,-experimental-zicfilp,-experimental-zicfiss,-experimental-ztso,-experimental-zvfbfmin,-experimental-zvfbfwma,-h,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smepmp,-smstateen,-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,-zama16b,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmop,-zcmp,-zcmt,-zdinx,-zfa,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zihintntl,-zihintpause,-zihpm,-zimop,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-zmmul,-zvbb,-zvbc,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl4096b,-zvl512b,-zvl65536b,-zvl8192b" }
attributes #1 = { nofree nounwind uwtable vscale_range(2,1024) "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic-rv64" "target-features"="+64bit,+a,+c,+d,+f,+m,+relax,+v,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b,-e,-experimental-smmpm,-experimental-smnpm,-experimental-ssnpm,-experimental-sspm,-experimental-ssqosid,-experimental-supm,-experimental-zaamo,-experimental-zabha,-experimental-zalasr,-experimental-zalrsc,-experimental-zfbfmin,-experimental-zicfilp,-experimental-zicfiss,-experimental-ztso,-experimental-zvfbfmin,-experimental-zvfbfwma,-h,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smepmp,-smstateen,-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,-zama16b,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmop,-zcmp,-zcmt,-zdinx,-zfa,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zihintntl,-zihintpause,-zihpm,-zimop,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-zmmul,-zvbb,-zvbc,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl4096b,-zvl512b,-zvl65536b,-zvl8192b" }
attributes #2 = { nofree nounwind "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic-rv64" "target-features"="+64bit,+a,+c,+d,+f,+m,+relax,+v,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b,-e,-experimental-smmpm,-experimental-smnpm,-experimental-ssnpm,-experimental-sspm,-experimental-ssqosid,-experimental-supm,-experimental-zaamo,-experimental-zabha,-experimental-zalasr,-experimental-zalrsc,-experimental-zfbfmin,-experimental-zicfilp,-experimental-zicfiss,-experimental-ztso,-experimental-zvfbfmin,-experimental-zvfbfwma,-h,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smepmp,-smstateen,-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,-zama16b,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmop,-zcmp,-zcmt,-zdinx,-zfa,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zihintntl,-zihintpause,-zihpm,-zimop,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-zmmul,-zvbb,-zvbc,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl4096b,-zvl512b,-zvl65536b,-zvl8192b" }
attributes #3 = { nounwind }

!0 = distinct !{!0, !1}
!1 = !{!"llvm.loop.mustprogress"}
```
LoopVectorize pass.

Looks like a sext/zext related issue.


commit d085b42cbbefe79a41113abcd2b1e1f2a203acef
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Wed May 8 10:04:09 2024 +0800

    [InstSimplify] Do not simplify freeze in `simplifyWithOpReplaced` (#91215)

    See the LangRef:
    > All uses of a value returned by the same ‘freeze’ instruction are
    guaranteed to always observe the same value, while different ‘freeze’
    instructions may yield different values.

    It is incorrect to replace freezes with the simplified value.

    Proof:
    https://alive2.llvm.org/ce/z/3Dn9Cd
    https://alive2.llvm.org/ce/z/Qyh5h6

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

diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 4061dae83c10..37a7259a5cd0 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4312,6 +4312,10 @@ static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
   if (match(I, m_Intrinsic<Intrinsic::is_constant>()))
     return nullptr;

+  // Don't simplify freeze.
+  if (isa<FreezeInst>(I))
+    return nullptr;
+
   // Replace Op with RepOp in instruction operands.
   SmallVector<Value *, 8> NewOps;
   bool AnyReplaced = false;

target datalayout = "e-p:64:64-p1:16:16-p2:32:32:32-p3:64:64:64"

define i8 @test_replace_freeze_oneuse(i1 %x, i8 %y) {
  %ext = zext i1 %x to i8
  %shl = shl nuw i8 %ext, %y
  %shl.fr = freeze i8 %shl
  %sel = select i1 %x, i8 0, i8 %shl.fr
  ret i8 %sel
}

target datalayout = "e-p:64:64-p1:16:16-p2:32:32:32-p3:64:64:64"

declare void @use32(i32)

define i32 @sequence_select_with_same_cond_extra_use(i1 %c1, i1 %c2) {
  %s1 = select i1 %c1, i32 23, i32 45
  call void @use32(i32 %s1)
  %s2 = select i1 %c2, i32 666, i32 %s1
  %s3 = select i1 %c1, i32 789, i32 %s2
  ret i32 %s3
}

target datalayout = "e-p:64:64-p1:16:16-p2:32:32:32-p3:64:64:64"

define i8 @test_replace_freeze_multiuse(i1 %x, i8 %y) {
  %ext = zext i1 %x to i8
  %shl = shl nuw i8 %ext, %y
  %shl.fr = freeze i8 %shl
  %sel = select i1 %x, i8 0, i8 %shl.fr
  %add = add i8 %shl.fr, %sel
  ret i8 %add
}

[InstCombine] Miscompilation which simplifies a use of a multi-use freeze

Reduced test case: https://alive2.llvm.org/ce/z/_JyUGw
```
define i8 @func78(i1 %0, i8 %1) {
  %3 = zext i1 %0 to i8
  %4 = shl i8 %3, %1
  %5 = freeze i8 %4
  %6 = select i1 %0, i8 0, i8 %5
  %7 = call i8 @llvm.fshr.i8(i8 0, i8 %5, i8 %6)
  ret i8 %7
}
```

```
----------------------------------------
define i8 @func78(i1 %#0, i8 %#1) {
#2:
  %#3 = zext i1 %#0 to i8
  %#4 = shl i8 %#3, %#1
  %#5 = freeze i8 %#4
  %#6 = select i1 %#0, i8 0, i8 %#5
  %#7 = fshr i8 0, i8 %#5, i8 %#6
  ret i8 %#7
}
=>
define i8 @func78(i1 %#0, i8 %#1) nofree noundef willreturn memory(none) {
#2:
  %#3 = zext i1 %#0 to i8
  %#4 = shl nuw i8 %#3, %#1
  %#5 = freeze i8 %#4
  ret i8 %#5
}
Transformation doesn't verify!

ERROR: Value mismatch

Example:
i1 %#0 = #x0 (0)
i8 %#1 = #x08 (8)

Source:
i8 %#3 = #x00 (0)
i8 %#4 = poison
i8 %#5 = #x00 (0)
i8 %#6 = #x00 (0)
i8 %#7 = #x00 (0)

Target:
i8 %#3 = #x00 (0)
i8 %#4 = poison
i8 %#5 = #x9d (157, -99)
Source value: #x00 (0)
Target value: #x9d (157, -99)

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


commit 883887493c882d656d5da100ee637a348e81357c
Author: Nikita Popov <npopov@redhat.com>
Date:   Tue Apr 23 12:36:35 2024 +0900

    [SimplifyCFG] Check alignment when speculating stores

    When speculating a store based on a preceding load/store, we need
    to ensure that the speculated store does not have a higher
    alignment (which might only be guaranteed by the branch condition).

    There are various ways in which this could be strengthened (we
    could get or enforce the alignment), but for now just do the
    simple check against the preceding load/store.

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

diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index da3eb229c041..0826d748ba0d 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -2888,7 +2888,8 @@ static Value *isSafeToSpeculateStore(Instruction *I, BasicBlock *BrBB,
       // simple, to avoid introducing a spurious non-atomic write after an
       // atomic write.
       if (SI->getPointerOperand() == StorePtr &&
-          SI->getValueOperand()->getType() == StoreTy && SI->isSimple())
+          SI->getValueOperand()->getType() == StoreTy && SI->isSimple() &&
+          SI->getAlign() >= StoreToHoist->getAlign())
         // Found the previous store, return its value operand.
         return SI->getValueOperand();
       return nullptr; // Unknown store.
@@ -2896,7 +2897,7 @@ static Value *isSafeToSpeculateStore(Instruction *I, BasicBlock *BrBB,

     if (auto *LI = dyn_cast<LoadInst>(&CurI)) {
       if (LI->getPointerOperand() == StorePtr && LI->getType() == StoreTy &&
-          LI->isSimple()) {
+          LI->isSimple() && LI->getAlign() >= StoreToHoist->getAlign()) {
         // Local objects (created by an `alloca` instruction) are always
         // writable, so once we are past a read from a location it is valid to
         // also write to that same location.

opt -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S < %s

define void @wrong_align_store(ptr %A, i32 %B, i32 %C, i32 %D) {
entry:
  store i32 %B, ptr %A, align 4
  %cmp = icmp sgt i32 %D, 42
  br i1 %cmp, label %if.then, label %ret.end

if.then:                                          ; preds = %entry
  store i32 %C, ptr %A, align 8
  br label %ret.end

ret.end:                                          ; preds = %if.then, %entry
  ret void
}

define void @wrong_align_load(i32 %C, i32 %D) {
entry:
  %A = alloca i32, align 4
  %0 = load i32, ptr %A, align 4
  %cmp = icmp sgt i32 %D, 42
  br i1 %cmp, label %if.then, label %ret.end

if.then:                                          ; preds = %entry
  store i32 %C, ptr %A, align 8
  br label %ret.end

ret.end:                                          ; preds = %if.then, %entry
  ret void
}

coalescing of redundant vector stores isn't preserving alignment correctly

https://alive2.llvm.org/ce/z/-qQphe

optimizing this code:
```llvm
define i32 @f(ptr %0, i1 %1) {
  store <2 x i64> zeroinitializer, ptr %0, align 8
  br i1 %1, label %4, label %3

3:                                                ; preds = %2
  store <2 x i64> zeroinitializer, ptr %0, align 16
  br label %4

4:                                                ; preds = %3, %2
  ret i32 0
}
```

is mostly doing what we expect, but the coalesced store should retain the smaller alignnment value of the two, not the larger:
```lllvm
define noundef i32 @f(ptr nocapture writeonly %0, i1 %1) local_unnamed_addr #0 {
  store <2 x i64> zeroinitializer, ptr %0, align 16
  ret i32 0
}

attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
```

cc @nunoplopes @hatsunespica

The issue is introduced by SimplifyCFG: https://alive2.llvm.org/ce/z/zf-j74

Specifically this is isSafeToSpeculateStore(), which looks for a preceding store to check whether it is safe to speculate, but fails to check alignment.


commit cff8d716bdf017a2af8eb8623257fd33ee43f30e
Author: v01dXYZ <14996868+v01dXYZ@users.noreply.github.com>
Date:   Tue Jul 9 09:14:33 2024 +0200

    [SCEV] forgetValue: support (with-overflow-inst op0, op1) (#98015)

    The use-def walk in forgetValue() was skipping instructions with
    non-SCEVable types. However, SCEV may look past with.overflow
    intrinsics returning aggregates.

    Fixes #97586.

diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 430e1c6d8f8c..51cffac80876 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -8412,7 +8412,7 @@ void ScalarEvolution::visitAndClearUsers(
     SmallVectorImpl<const SCEV *> &ToForget) {
   while (!Worklist.empty()) {
     Instruction *I = Worklist.pop_back_val();
-    if (!isSCEVable(I->getType()))
+    if (!isSCEVable(I->getType()) && !isa<WithOverflowInst>(I))
       continue;

     ValueExprMapType::iterator It =

opt < %s -S  -passes='print<scalar-evolution>,loop-unroll<peeling;full-unroll-max=0>,print<scalar-evolution>' 2>&1

;
; This test ensures that (extractvalue 0 (with-overflow-inst op0, op1))
; is invalidated by LoopPeel when the operands of with-overflow-inst
; are changed.
;
; In the following case, LoopPeel modifies the CFG into another one
; with %bb7 not dominating %bb2 and %bb3 although %extractvalue is
; still the step for the %bb3 loop. %call has been modified and uses
; different operands but the SCEV value for %extractvalue has not been
; invalidated and still refers to %load in its SCEV operands
; (SCEV(%extractvalue) := -2 + -2 * %load).
;
; When LoopUnroll tries to compute the SCEV for the %bb3 Phi, the
; stale data for %extractvalue is used whereas %load is not available
; in %bb3 which is wrong.
;
; for more details and nice pictures: https://github.com/llvm/llvm-project/issues/97586
;
; Although the reason for the bug was in forgetValue, it is still relevant to
; test if LoopPeel invalidates %extractvalue after changing %call.
;
; forgetValue only walks the users, so calling it on the IV Phis does not
; invalidate %extractvalue (thus forgetLoop does not invalidate it too).
; It has to be done by LoopPeel itself.

define void @loop_peeling_smul_with_overflow() {
; before loop-unroll
; after loop-unroll
;
bb:
  br label %bb1

bb1:                                              ; preds = %bb3, %bb
  %phi = phi i32 [ 0, %bb ], [ %phi4, %bb3 ]
  br label %bb5

bb2:                                              ; preds = %bb7
  %call = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %add8, i32 -2)
  %extractvalue = extractvalue { i32, i1 } %call, 0
  br label %bb3

bb3:                                              ; preds = %bb3, %bb2
  %phi4 = phi i32 [ %add, %bb3 ], [ 0, %bb2 ]
  %add = add i32 %extractvalue, %phi4
  br i1 false, label %bb3, label %bb1

bb5:                                              ; preds = %bb7, %bb1
  %phi6 = phi i32 [ 1, %bb1 ], [ 0, %bb7 ]
  %icmp = icmp eq i32 %phi, 0
  br i1 %icmp, label %bb9, label %bb7

bb7:                                              ; preds = %bb5
  %load = load i32, ptr addrspace(1) null, align 4
  %add8 = add i32 %load, 1
  br i1 false, label %bb2, label %bb5

bb9:                                              ; preds = %bb5
  ret void
}

Assertion Failure in `getSCEV` during loop unroll

```
; ModuleID = '<stdin>'
source_filename = "<stdin>"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128-ni:1-p2:32:8:8:32-ni:2"
target triple = "x86_64-unknown-linux-gnu"

define void @ham() {
bb:
  br label %bb1

bb1:                                              ; preds = %bb3, %bb
  %phi = phi i32 [ 0, %bb ], [ %phi4, %bb3 ]
  br label %bb5

bb2:                                              ; preds = %bb7
  %call = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %add8, i32 -2)
  %extractvalue = extractvalue { i32, i1 } %call, 0
  br label %bb3

bb3:                                              ; preds = %bb3, %bb2
  %phi4 = phi i32 [ %add, %bb3 ], [ 0, %bb2 ]
  %add = add i32 %extractvalue, %phi4
  br i1 false, label %bb3, label %bb1

bb5:                                              ; preds = %bb7, %bb1
  %phi6 = phi i32 [ 1, %bb1 ], [ 0, %bb7 ]
  %icmp = icmp eq i32 %phi, 0
  br i1 %icmp, label %bb9, label %bb7

bb7:                                              ; preds = %bb5
  %load = load i32, ptr addrspace(1) null, align 4
  %add8 = add i32 %load, 1
  br i1 false, label %bb2, label %bb5

bb9:                                              ; preds = %bb5
  ret void
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare { i32, i1 } @llvm.smul.with.overflow.i32(i32, i32) #0

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
```
crashes with the below backtrace when run with `opt --passes="print<scalar-evolution>,loop-unroll<no-partial;peeling;no-runtime;no-upperbound;no-profile-peeling;full-unroll-max=0;O3> <filename.ll>"`
```
opt: /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:3678: const llvm::SCEV* llvm::ScalarEvolution::getAddRecExpr(llvm::SmallVectorImpl<const llvm::SCEV*>&, const llvm::Loop*, llvm::SCEV::NoWrapFlags): Assertion `isAvailableAtLoopEntry(Operands[i], L) && "SCEVAddRecExpr operand is not available at loop entry!"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: /home/manishkh/Workspace7/orcaInstall/installDA/bin/opt --passes=print<scalar-evolution>,loop-unroll<no-partial;peeling;no-runtime;no-upperbound;no-profile-peeling;full-unroll-max=0;O3> reduced2.ll -disable-output
 #0 0x00007f272f49aa72 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /home/manishkh/Workspace7/orca/llvm/lib/Support/Unix/Signals.inc:723:0
 #1 0x00007f272f49aeaf PrintStackTraceSignalHandler(void*) /home/manishkh/Workspace7/orca/llvm/lib/Support/Unix/Signals.inc:798:0
 #2 0x00007f272f498793 llvm::sys::RunSignalHandlers() /home/manishkh/Workspace7/orca/llvm/lib/Support/Signals.cpp:105:0
 #3 0x00007f272f49a459 SignalHandler(int) /home/manishkh/Workspace7/orca/llvm/lib/Support/Unix/Signals.inc:413:0
 #4 0x00007f2738fd7630 __restore_rt sigaction.c:0:0
 #5 0x00007f272b893387 raise (/lib64/libc.so.6+0x36387)
 #6 0x00007f272b894a78 abort (/lib64/libc.so.6+0x37a78)
 #7 0x00007f272b88c1a6 __assert_fail_base (/lib64/libc.so.6+0x2f1a6)
 #8 0x00007f272b88c252 (/lib64/libc.so.6+0x2f252)
 #9 0x00007f2732031da6 llvm::ScalarEvolution::getAddRecExpr(llvm::SmallVectorImpl<llvm::SCEV const*>&, llvm::Loop const*, llvm::SCEV::NoWrapFlags) /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:3677:0
#10 0x00007f2732031b29 llvm::ScalarEvolution::getAddRecExpr(llvm::SCEV const*, llvm::SCEV const*, llvm::Loop const*, llvm::SCEV::NoWrapFlags) /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:3660:0
#11 0x00007f2732039c11 llvm::ScalarEvolution::createSimpleAffineAddRec(llvm::PHINode*, llvm::Value*, llvm::Value*) /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:5776:0
#12 0x00007f2732039f65 llvm::ScalarEvolution::createAddRecFromPHI(llvm::PHINode*) /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:5831:0
#13 0x00007f273203aadf llvm::ScalarEvolution::createNodeForPHI(llvm::PHINode*) /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:6025:0
#14 0x00007f273204562a llvm::ScalarEvolution::createSCEV(llvm::Value*) /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:8069:0
#15 0x00007f2732042338 llvm::ScalarEvolution::createSCEVIter(llvm::Value*) /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:7447:0
#16 0x00007f2732035a05 llvm::ScalarEvolution::getSCEV(llvm::Value*) /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:4572:0
#17 0x00007f273203ab71 llvm::ScalarEvolution::createNodeForPHI(llvm::PHINode*) /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:6029:0
#18 0x00007f273204562a llvm::ScalarEvolution::createSCEV(llvm::Value*) /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:8069:0
#19 0x00007f2732042338 llvm::ScalarEvolution::createSCEVIter(llvm::Value*) /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:7447:0
#20 0x00007f2732035a05 llvm::ScalarEvolution::getSCEV(llvm::Value*) /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:4572:0
#21 0x00007f2732039fcf llvm::ScalarEvolution::createAddRecFromPHI(llvm::PHINode*) /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:5840:0
#22 0x00007f273203aadf llvm::ScalarEvolution::createNodeForPHI(llvm::PHINode*) /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:6025:0
#23 0x00007f273204562a llvm::ScalarEvolution::createSCEV(llvm::Value*) /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:8069:0
#24 0x00007f2732042338 llvm::ScalarEvolution::createSCEVIter(llvm::Value*) /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:7447:0
#25 0x00007f2732035a05 llvm::ScalarEvolution::getSCEV(llvm::Value*) /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:4572:0
#26 0x00007f273204a26a llvm::ScalarEvolution::computeExitLimitFromICmp(llvm::Loop const*, llvm::ICmpInst*, bool, bool, bool) /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:9117:0
#27 0x00007f273204971e llvm::ScalarEvolution::computeExitLimitFromCondImpl(llvm::ScalarEvolution::ExitLimitCache&, llvm::Loop const*, llvm::Value*, bool, bool, bool) /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:8975:0
#28 0x00007f273204955b llvm::ScalarEvolution::computeExitLimitFromCondCached(llvm::ScalarEvolution::ExitLimitCache&, llvm::Loop const*, llvm::Value*, bool, bool, bool) /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:8958:0
#29 0x00007f27320491a4 llvm::ScalarEvolution::computeExitLimitFromCond(llvm::Loop const*, llvm::Value*, bool, bool, bool) /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:8914:0
#30 0x00007f2732048f49 llvm::ScalarEvolution::computeExitLimit(llvm::Loop const*, llvm::BasicBlock*, bool) /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:8888:0
#31 0x00007f27320488db llvm::ScalarEvolution::computeBackedgeTakenCount(llvm::Loop const*, bool) /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:8797:0
#32 0x00007f27320469fb llvm::ScalarEvolution::getBackedgeTakenInfo(llvm::Loop const*) /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:8358:0
#33 0x00007f27320464ab llvm::ScalarEvolution::getExitCount(llvm::Loop const*, llvm::BasicBlock const*, llvm::ScalarEvolution::ExitCountKind) /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:8270:0
#34 0x00007f27320460c6 llvm::ScalarEvolution::getSmallConstantTripCount(llvm::Loop const*, llvm::BasicBlock const*) /home/manishkh/Workspace7/orca/llvm/lib/Analysis/ScalarEvolution.cpp:8203:0
#35 0x00007f273146141a tryToUnrollLoop(llvm::Loop*, llvm::DominatorTree&, llvm::LoopInfo*, llvm::ScalarEvolution&, llvm::TargetTransformInfo const&, llvm::AssumptionCache&, llvm::OptimizationRemarkEmitter&, llvm::BlockFrequencyInfo*, llvm::ProfileSummaryInfo*, bool, int, bool, bool, bool, std::optional<unsigned int>, std::optional<unsigned int>, std::optional<bool>, std::optional<bool>, std::optional<bool>, std::optional<bool>, std::optional<bool>, std::optional<unsigned int>, llvm::AAResults*) /home/manishkh/Workspace7/orca/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp:1259:0
#36 0x00007f2731462e2c llvm::LoopUnrollPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) /home/manishkh/Workspace7/orca/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp:1658:0
#37 0x00007f27339727ac llvm::detail::PassModel<llvm::Function, llvm::LoopUnrollPass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) /home/manishkh/Workspace7/orca/llvm/include/llvm/IR/PassManagerInternal.h:91:0
#38 0x00007f272f831f82 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) /home/manishkh/Workspace7/orca/llvm/include/llvm/IR/PassManager.h:228:0
#39 0x00007f27331d1e32 llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) /home/manishkh/Workspace7/orca/llvm/include/llvm/IR/PassManagerInternal.h:91:0
#40 0x00007f272f830d12 llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) /home/manishkh/Workspace7/orca/llvm/lib/IR/PassManager.cpp:128:0
#41 0x00007f27331d1d96 llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) /home/manishkh/Workspace7/orca/llvm/include/llvm/IR/PassManagerInternal.h:91:0
#42 0x00007f272f831c5a llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) /home/manishkh/Workspace7/orca/llvm/include/llvm/IR/PassManager.h:228:0
#43 0x00000000004acc3e 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) /home/manishkh/Workspace7/orca/llvm/tools/opt/NewPMDriver.cpp:559:0
#44 0x0000000000477a33 optMain /home/manishkh/Workspace7/orca/llvm/tools/opt/optdriver.cpp:756:0
#45 0x000000000047540f main /home/manishkh/Workspace7/orca/llvm/tools/opt/opt.cpp:25:0
#46 0x00007f272b87f555 __libc_start_main (/lib64/libc.so.6+0x22555)
#47 0x00000000004752c9 _start (/home/manishkh/Workspace7/orcaInstall/installDA/bin/opt+0x4752c9)
```

as demonstrated by this godbolt example: https://godbolt.org/z/be3a4Yr9e

I did some preliminary analysis on this bug, and here is what I found:
The IR at the point of crash looks like this:
```
define zing void @ham() {
bb:
  br label %bb1

bb1.loopexit:                                     ; preds = %bb3
  %phi4.lcssa = phi i32 [ %phi4, %bb3 ]
  br label %bb1

bb1:                                              ; preds = %bb1.loopexit, %bb
  %phi = phi i32 [ 0, %bb ], [ %phi4.lcssa, %bb1.loopexit ]
  br label %bb5.peel.begin

bb5.peel.begin:                                   ; preds = %bb1
  br label %bb5.peel

bb5.peel:                                         ; preds = %bb5.peel.begin, exiting
  %icmp.peel = icmp eq i32 %phi, 0
  br i1 %icmp.peel, label %bb9.loopexit2, label %bb7.peel

bb7.peel:                                         ; preds = %bb5.peel
  %load.peel = load i32, ptr addrspace(1) null, align 4
  %add8.peel = add i32 %load.peel, 1
  br i1 false, label %bb2, label %bb5.peel.next

bb5.peel.next:                                    ; preds = %bb7.peel
  br label %bb5.peel.next1

bb5.peel.next1:                                   ; preds = %bb5.peel.next
  br label %bb1.peel.newph

bb1.peel.newph:                                   ; preds = %bb5.peel.next1
  br label %bb5

bb2.loopexit:                                     ; preds = %bb7
  %add8.lcssa.ph = phi i32 [ %add8, %bb7 ]
  br label %bb2

bb2:                                              ; preds = %bb2.loopexit, %bb7.peel
  %add8.lcssa = phi i32 [ %add8.peel, %bb7.peel ], [ %add8.lcssa.ph, %bb2.loopexit ]
  %call = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %add8.lcssa, i32 -2)
  %extractvalue = extractvalue { i32, i1 } %call, 0
  br label %bb3

bb3:                                              ; preds = %bb3, %bb2
  %phi4 = phi i32 [ %add, %bb3 ], [ 0, %bb2 ]
  %add = add i32 %extractvalue, %phi4
  br i1 false, label %bb3, label %bb1.loopexit

bb5:                                              ; preds = %bb7, %bb1.peel.newph, exiting
  br i1 false, label %bb9.loopexit, label %bb7

bb7:                                              ; preds = %bb5
  %load = load i32, ptr addrspace(1) null, align 4
  %add8 = add i32 %load, 1
  br i1 false, label %bb2.loopexit, label %bb5, !llvm.loop !0

bb9.loopexit:                                     ; preds = %bb5
  br label %bb9

bb9.loopexit2:                                    ; preds = %bb5.peel
  br label %bb9

bb9:                                              ; preds = %bb9.loopexit2, %bb9.loopexit
  ret void
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare { i32, i1 } @llvm.smul.with.overflow.i32(i32, i32) #0

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
```
We have 3 loops in this this IR(1 outer and 2 inner, out of which the bb5-bb7 loop has been peeled.):
```
Loop at depth 1 containing: %bb1<header>,%bb5<exiting>,%bb7,%bb2,%bb3,%bb1.loopexit<latch>,%bb5.peel.begin,%bb5.peel.next,%bb1.peel.newph,%bb5.peel<exiting>,%bb7.peel,%bb5.peel.next1
    Loop at depth 2 containing: %bb5<header><exiting>,%bb7<latch><exiting>
    Loop at depth 2 containing: %bb3<header><latch><exiting>
```
Here is the CFG for this IR:
![Screenshot 2024-07-03 at 8 24 52 PM](https://github.com/llvm/llvm-project/assets/46352931/02e57740-9ef6-4945-868e-62a645325552)

The assertion fails because SCEV expects bb7 to properly dominate bb3, which it does in the old IR, but after peeling, it does not. This seems to arise from the fact that SCEVs in %bb2 have not been invalidated after the peeling. I see that the SCEV for `%extractvalue` comes from the ValueExprMap instead of being recomputed, following the peel, and the use of this invalid SCEV is what I think is causing the problem.

Perhaps these updates to SE are not enough?
https://github.com/llvm/llvm-project/blob/86d456ad8f2aef6edcc36d44d26119025331981e/llvm/lib/Transforms/Utils/LoopPeel.cpp#L1088-L1090

@nikic @fhahn @RKSimon  is `forgetTopmostLoop` supposed to forget SCEV of all SSA values inside the loop(ie, header, latch and other blocks) ? I see that its implementation does not do that currently.

@Nirhar Generally no. It forgets information about induction variables (things based on loop header phis), as well as information pertaining to the loop (such as BECounts, exit values etc), but not of literally everything defined in the loop.

From a super quick look, the issue here might be that the exit phi forgetValue() calls don't invalidate enough values due to the condition at https://github.com/llvm/llvm-project/blob/e55585fd7bddf5bb3824a53cbe2971206d3c20c6/llvm/lib/Analysis/ScalarEvolution.cpp#L8415, which means that we will stop at the aggregate results of with.overflow intrinsics, even though SCEV can look through them. It might be that they need special handling.

When replacing the `smul.with.overflow + extractvalue` by a `mul`, it doesn't abort.
When removing the SCEVable check, it doesn't abort.

The function that allows to traverse unSCEVable when creating the SCEV is `MatchBinaryOp` (cf `createSimpleAffineRec`). We could make this function returns a subset of the use-def to SCEVable or have another function that do the reverse with a def-use matching.

I think that the issue might be something else. From my analysis, here is how the control flow goes:
1. When we hit `forgetTopmostLoop`, we try to forget the SCEV values of the loop:
```
Loop at depth 1 containing: %bb1<header>,%bb5<exiting>,%bb7,%bb2,%bb3,%bb1.loopexit<latch>,%bb5.peel.begin,%bb5.peel.next,%bb1.peel.newph,%bb5.peel<exiting>,%bb7.peel,%bb5.peel.next1
    Loop at depth 2 containing: %bb5<header><exiting>,%bb7<latch><exiting>
    Loop at depth 2 containing: %bb3<header><latch><exiting>
```
We first take the phi node in the header `%phi = phi i32 [ 0, %bb ], [ %phi4.lcssa, %bb1.loopexit ]` and start the DFS from there. From here, we go to the following nodes:(` %icmp.peel = icmp eq i32 %phi, 0` , ` br i1 %icmp.peel, label %bb9.loopexit2, label %bb7.peel` and now non existent `%icmp = icmp eq i32 %phi, 0` , `br i1 %icmp, label %bb9, label %bb7`. The DFS for the outer loop ends here.

2. Next we traverse the inner loop:
```
Loop at depth 2 containing: %bb3<header><latch><exiting>
```
Here we start with phi node in the header `%phi4 = phi i32 [ %add, %bb3 ], [ 0, %bb2 ]` and then traverse through the nodes: `%add = add i32 %extractvalue, %phi4` and `%phi4.lcssa = phi i32 [ %phi4, %bb3 ]`, after which we quit traversal.

3. Finally we visit the inner loop:
```
Loop at depth 2 containing: %bb5<header><exiting>,%bb7<latch><exiting>
```
We start and end DFS at (now non-existent)`%phi6 = phi i32 [ 0, %bb1.peel.newph ], [ 0, %bb7 ]`.

**_TLDR_**; Throughout the entire traversal, we never visit the basic block bb2, and never invalidate its SCEV values. We don't even visit smul intrinsic call to forget its SCEV. Perhaps one needs to consider use-def chains to forget SCEV values, similar to the now considered def-use chain.

Note: The IR at the point of crash is slightly different from the IR after the previous loop-peel. I've used the term `now non-existent` to mean that that node is not present in the IR at the crash point.

@Nirhar The forgetTopmostLoop() call is not what is responsible for the invalidation here, it's the forgetValue() call on the LCSSA phis in https://github.com/llvm/llvm-project/blob/27ccc8835e5163484234549fa6128eeb00d7432d/llvm/lib/Transforms/Utils/LoopPeel.cpp#L862

Aah sorry, I missed that. Thanks for pointing it out!


commit 3c127e83c07c3791e86413c22a414a030d4302e3
Author: Florian Hahn <flo@fhahn.com>
Date:   Tue Jan 2 22:05:57 2024 +0000

    [ConstraintElim] Replace NUWSub decomp with recursive decomp of ops.

    The current patterns for NUWSub decompositions do not handle negative
    constants correctly at the moment (causing #76713).

    Replace the incorrect pattern by more general code that recursively
    decomposes the operands and then combines the results. This is already
    done in most other places that handle operators like add/mul.

    This means we fall back to the general constant handling code (fixes the
    mis-compile) while also being able to support reasoning about
    decomposable expressions in the SUB operands.

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

diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index 49ac1e96e255..06c87bd6dc37 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -366,6 +366,13 @@ struct Decomposition {
     append_range(Vars, Other.Vars);
   }

+  void sub(const Decomposition &Other) {
+    Decomposition Tmp = Other;
+    Tmp.mul(-1);
+    add(Tmp.Offset);
+    append_range(Vars, Tmp.Vars);
+  }
+
   void mul(int64_t Factor) {
     Offset = multiplyWithOverflow(Offset, Factor);
     for (auto &Var : Vars)
@@ -569,10 +576,12 @@ static Decomposition decompose(Value *V,
     return Result;
   }

-  if (match(V, m_NUWSub(m_Value(Op0), m_ConstantInt(CI))) && canUseSExt(CI))
-    return {-1 * CI->getSExtValue(), {{1, Op0}}};
-  if (match(V, m_NUWSub(m_Value(Op0), m_Value(Op1))))
-    return {0, {{1, Op0}, {-1, Op1}}};
+  if (match(V, m_NUWSub(m_Value(Op0), m_Value(Op1)))) {
+    auto ResA = decompose(Op0, Preconditions, IsSigned, DL);
+    auto ResB = decompose(Op1, Preconditions, IsSigned, DL);
+    ResA.sub(ResB);
+    return ResA;
+  }

   return {V, IsKnownNonNegative};
 }

opt -passes=constraint-elimination -S %s

define i1 @pr76713(i16 %i1, i16 %i3) {
entry:
  %c1 = icmp ult i16 %i1, -1
  %c2 = icmp uge i16 %i1, -3
  %c3 = icmp ult i16 %i3, 2
  %and = and i1 %c1, %c2
  %and.2 = and i1 %and, %c3
  br i1 %and, label %then, label %else

then:                                             ; preds = %entry
  %sub = sub nuw nsw i16 %i1, -3
  %arrayidx.idx = mul nuw nsw i16 %i3, 4
  %i6 = add nuw nsw i16 %arrayidx.idx, %sub
  %c4 = icmp ult i16 12, %i6
  ret i1 %c4

else:                                             ; preds = %entry
  ret i1 false
}

declare void @use(i1)

define void @sub_nuw_chained_negative_constants(i8 %a) {
entry:
  %sub1 = sub nuw i8 %a, 10
  %sub2 = sub nuw i8 %sub1, -126
  %c.1 = icmp ugt i8 %sub2, 20
  br i1 %c.1, label %exit.1, label %exit.2

exit.1:                                           ; preds = %entry
  %c.2 = icmp ugt i8 %a, -96
  call void @use(i1 %c.2)
  %c.3 = icmp ugt i8 %a, -95
  call void @use(i1 %c.3)
  ret void

exit.2:                                           ; preds = %entry
  %c.4 = icmp ugt i8 %a, -96
  call void @use(i1 %c.4)
  %c.5 = icmp ugt i8 %a, -95
  call void @use(i1 %c.5)
  ret void
}

define i1 @sub_nuw_neg_i16(i16 %a) {
entry:
  %neg2 = sub nuw i16 %a, -305
  %c.1 = icmp ugt i16 0, %neg2
  br i1 %c.1, label %exit.1, label %exit.2

exit.1:                                           ; preds = %entry
  %c.2 = icmp ugt i16 %a, 0
  ret i1 %c.2

exit.2:                                           ; preds = %entry
  %c.3 = icmp ugt i16 %a, 0
  ret i1 %c.3
}

declare void @use(i1)

define void @sub_nuw_chained_positive_constants(i16 %a) {
entry:
  %sub1 = sub nuw i16 %a, 10
  %sub2 = sub nuw i16 %sub1, 20
  %c.1 = icmp ugt i16 %sub2, 90
  br i1 %c.1, label %exit.1, label %exit.2

exit.1:                                           ; preds = %entry
  %c.2 = icmp ugt i16 %a, 120
  call void @use(i1 %c.2)
  %c.3 = icmp ugt i16 %a, 121
  call void @use(i1 %c.3)
  ret void

exit.2:                                           ; preds = %entry
  %c.4 = icmp ugt i16 %a, 120
  call void @use(i1 %c.4)
  %c.5 = icmp ugt i16 %a, 121
  call void @use(i1 %c.5)
  ret void
}

Miscompile with opt -passes="constraint-elimination"

llvm commit: 5842dfe34d89
Reproduce with: ```opt -passes="constraint-elimination" bbi-90501.ll -S -o -```
[bbi-90501.ll.gz](https://github.com/llvm/llvm-project/files/13810077/bbi-90501.ll.gz)

There are two nested loops in the input that should finish and then we should end up at
```
bb.2:                                             ; preds = %bb.1
  ret i16 0
```
but with constraint-elimination the condition in bb.5 is changed to
```
  %i10 = or i1 true, %i9
  br i1 %i10, label %bb.7, label %bb.6
```
so we will go to
```
bb.7:                                             ; preds = %bb.5
  ret i16 1
```
instead.

This starts happening with e6a1657fa30c747f4412fc47f567660ebe861a9e
```
[ConstraintElim] Add A < B if A is an increasing phi for A != B.
```
@fhahn : any idea what's up?

Looks like an issue with `sub` decomposition with negative constants, preparing a fix.

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

@mikaelholmen thanks for the reproducer!

(appreciated as always, thanks for your extensive testing)


commit 03d8831fa8ef5b7e32172c718b550a454645faea
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Tue Nov 19 22:17:24 2024 +0800

    [InstCombine] Handle constant GEP expr in `SimplifyDemandedUseBits` (#116794)

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

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 5eb807dcb76c..392c5c78345c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -997,7 +997,7 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Instruction *I,
             uint64_t MaskedGEPIndex = HighBitsGEPIndex | MaskedLowBitsGEPIndex;

             if (MaskedGEPIndex != GEPIndex) {
-              auto *GEP = cast<GetElementPtrInst>(II->getArgOperand(0));
+              auto *GEP = cast<GEPOperator>(II->getArgOperand(0));
               Builder.SetInsertPoint(I);
               Type *GEPIndexType =
                   DL.getIndexType(GEP->getPointerOperand()->getType());

target datalayout = "p1:64:64:64:32"

@GC_arrays = external global { i8, i8, i64 }

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

define ptr @ptrmask_demandedbits_constantexpr() {
entry:
  %aligned_result = call ptr @llvm.ptrmask.p0.i64(ptr getelementptr inbounds (i8, ptr @GC_arrays, i64 1), i64 -8)
  ret ptr %aligned_result
}

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

target datalayout = "p1:64:64:64:32"

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

define ptr @ptrmask_is_useless_fail1(i64 %i, i64 %m) {
  %m0 = and i64 %m, 127
  %i0 = and i64 %i, 511
  %p0 = inttoptr i64 %i0 to ptr
  %r = call ptr @llvm.ptrmask.p0.i64(ptr %p0, i64 %m0)
  ret ptr %r
}

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

Segfault when building https://github.com/ivmai/bdwgc@4fe4238

Attempting to build [https://github.com/ivmai/bdwgc@4fe4238](https://github.com/ivmai/bdwgc/tree/4fe42389509ff059bad8d4c955a570b34a6bda4b) using
```shell
$ ./autogen.sh
$ ./configure --with-libatomic-ops --enable-cplusplus --enable-large-config
$ make
```
results in
```text
libtool: compile:  clang -std=gnu23 -DHAVE_CONFIG_H -I./include -I./include -DNDEBUG -fexceptions -DGC_VISIBILITY_HIDDEN_SET -fvisibility=hidden -Wall -Wextra -Wpedantic -Wno-long-long -O2 -march=native -Wno-frame-address -MT extra/gc.lo -MD -MP -MF extra/.deps/gc.Tpo -c extra/gc.c  -fno-common -DPIC -o extra/.libs/gc.o
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: clang -std=gnu23 -DHAVE_CONFIG_H -I./include -I./include -DNDEBUG -fexceptions -DGC_VISIBILITY_HIDDEN_SET -fvisibility=hidden -Wall -Wextra -Wpedantic -Wno-long-long -O2 -march=native -Wno-frame-address -MT extra/gc.lo -MD -MP -MF extra/.deps/gc.Tpo -c extra/gc.c -fno-common -DPIC -o extra/.libs/gc.o
1.	<eof> parser at end of file
2.	Optimizer
3.	Running pass "require<globals-aa>,function(invalidate<aa>),require<profile-summary>,cgscc(devirt<4>(inline,function-attrs<skip-non-recursive-function-attrs>,openmp-opt-cgscc,function<eager-inv;no-rerun>(sroa<modify-cfg>,early-cse<memssa>,speculative-execution<only-if-divergent-target>,jump-threading,correlated-propagation,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,instcombine<max-iterations=1;no-verify-fixpoint>,aggressive-instcombine,libcalls-shrinkwrap,tailcallelim,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,reassociate,constraint-elimination,loop-mssa(loop-instsimplify,loop-simplifycfg,licm<no-allowspeculation>,loop-rotate<header-duplication;no-prepare-for-lto>,licm<allowspeculation>,simple-loop-unswitch<no-nontrivial;trivial>),simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,instcombine<max-iterations=1;no-verify-fixpoint>,loop(loop-idiom,indvars,simple-loop-unswitch<no-nontrivial;trivial>,loop-deletion,loop-unroll-full),sroa<modify-cfg>,vector-combine,mldst-motion<no-split-footer-bb>,gvn<>,sccp,bdce,instcombine<max-iterations=1;no-verify-fixpoint>,jump-threading,correlated-propagation,adce,memcpyopt,dse,move-auto-init,loop-mssa(licm<allowspeculation>),coro-elide,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,instcombine<max-iterations=1;no-verify-fixpoint>),function-attrs,function(require<should-not-run-function-passes>),coro-split,coro-annotation-elide)),function(invalidate<should-not-run-function-passes>),cgscc(devirt<4>())" on module "extra/gc.c"
4.	Running pass "cgscc(devirt<4>(inline,function-attrs<skip-non-recursive-function-attrs>,openmp-opt-cgscc,function<eager-inv;no-rerun>(sroa<modify-cfg>,early-cse<memssa>,speculative-execution<only-if-divergent-target>,jump-threading,correlated-propagation,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,instcombine<max-iterations=1;no-verify-fixpoint>,aggressive-instcombine,libcalls-shrinkwrap,tailcallelim,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,reassociate,constraint-elimination,loop-mssa(loop-instsimplify,loop-simplifycfg,licm<no-allowspeculation>,loop-rotate<header-duplication;no-prepare-for-lto>,licm<allowspeculation>,simple-loop-unswitch<no-nontrivial;trivial>),simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,instcombine<max-iterations=1;no-verify-fixpoint>,loop(loop-idiom,indvars,simple-loop-unswitch<no-nontrivial;trivial>,loop-deletion,loop-unroll-full),sroa<modify-cfg>,vector-combine,mldst-motion<no-split-footer-bb>,gvn<>,sccp,bdce,instcombine<max-iterations=1;no-verify-fixpoint>,jump-threading,correlated-propagation,adce,memcpyopt,dse,move-auto-init,loop-mssa(licm<allowspeculation>),coro-elide,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,instcombine<max-iterations=1;no-verify-fixpoint>),function-attrs,function(require<should-not-run-function-passes>),coro-split,coro-annotation-elide))" on module "extra/gc.c"
5.	Running pass "instcombine<max-iterations=1;no-verify-fixpoint>" on function "GC_push_finalizer_structures"
 #0 0x0000000112ecda98 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0x3299a98)
 #1 0x0000000112eccb47 llvm::sys::RunSignalHandlers() (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0x3298b47)
 #2 0x0000000112eccde1 llvm::sys::CleanupOnSignal(unsigned long) (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0x3298de1)
 #3 0x0000000112df2644 CrashRecoverySignalHandler(int) (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0x31be644)
 #4 0x00007ff81abe4fdd (/usr/lib/system/libsystem_platform.dylib+0x7ff80046afdd)
 #5 0x0000000112e1d131 computeForAddCarry(llvm::KnownBits const&, llvm::KnownBits const&, bool, bool) (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0x31e9131)
 #6 0x0000000112318cdd llvm::TargetFolder::FoldGEP(llvm::Type*, llvm::Value*, llvm::ArrayRef<llvm::Value*>, llvm::GEPNoWrapFlags) const (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0x26e4cdd)
 #7 0x00000001102d2177 llvm::IRBuilderBase::CreateGEP(llvm::Type*, llvm::Value*, llvm::ArrayRef<llvm::Value*>, llvm::Twine const&, llvm::GEPNoWrapFlags) (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0x69e177)
 #8 0x000000011209545a llvm::InstCombinerImpl::SimplifyDemandedUseBits(llvm::Instruction*, llvm::APInt const&, llvm::KnownBits&, unsigned int, llvm::SimplifyQuery const&) (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0x246145a)
 #9 0x0000000112097524 llvm::InstCombinerImpl::SimplifyDemandedInstructionBits(llvm::Instruction&, llvm::KnownBits&) (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0x2463524)
#10 0x0000000111ffc58b llvm::InstCombinerImpl::visitCallInst(llvm::CallInst&) (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0x23c858b)
#11 0x0000000111f85788 llvm::InstCombinerImpl::run() (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0x2351788)
#12 0x0000000111f765e2 combineInstructionsOverFunction(llvm::Function&, llvm::InstructionWorklist&, llvm::AAResults*, llvm::AssumptionCache&, llvm::TargetLibraryInfo&, llvm::TargetTransformInfo&, llvm::DominatorTree&, llvm::OptimizationRemarkEmitter&, llvm::BlockFrequencyInfo*, llvm::BranchProbabilityInfo*, llvm::ProfileSummaryInfo*, llvm::InstCombineOptions const&) (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0x23425e2)
#13 0x0000000111fc1b85 llvm::InstCombinePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0x238db85)
#14 0x0000000110596272 llvm::detail::PassModel<llvm::Function, llvm::InstCombinePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0x962272)
#15 0x0000000112b6736a llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0x2f3336a)
#16 0x000000011003f522 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/llvm-project@HEAD/lib/libLLVM.dylib+0x40b522)
#17 0x00000001122fe7db llvm::CGSCCToFunctionPassAdaptor::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0x26ca7db)
#18 0x0000000110b41712 llvm::detail::PassModel<llvm::LazyCallGraph::SCC, llvm::CGSCCToFunctionPassAdaptor, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0xf0d712)
#19 0x00000001122fa573 llvm::PassManager<llvm::LazyCallGraph::SCC, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0x26c6573)
#20 0x0000000110b3e332 llvm::detail::PassModel<llvm::LazyCallGraph::SCC, llvm::PassManager<llvm::LazyCallGraph::SCC, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0xf0a332)
#21 0x00000001122fcc0e llvm::DevirtSCCRepeatedPass::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0x26c8c0e)
#22 0x0000000110b413a2 llvm::detail::PassModel<llvm::LazyCallGraph::SCC, llvm::DevirtSCCRepeatedPass, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0xf0d3a2)
#23 0x00000001122fbe83 llvm::ModuleToPostOrderCGSCCPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0x26c7e83)
#24 0x0000000110b3e012 llvm::detail::PassModel<llvm::Module, llvm::ModuleToPostOrderCGSCCPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0xf0a012)
#25 0x0000000112b65a22 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0x2f31a22)
#26 0x0000000110d25d8b llvm::ModuleInlinerWrapperPass::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0x10f1d8b)
#27 0x0000000110594012 llvm::detail::PassModel<llvm::Module, llvm::ModuleInlinerWrapperPass, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0x960012)
#28 0x0000000112b65a22 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0x2f31a22)
#29 0x000000010788b478 (anonymous namespace)::EmitAssemblyHelper::RunOptimizationPipeline(clang::BackendAction, std::__1::unique_ptr<llvm::raw_pwrite_stream, std::__1::default_delete<llvm::raw_pwrite_stream>>&, std::__1::unique_ptr<llvm::ToolOutputFile, std::__1::default_delete<llvm::ToolOutputFile>>&, clang::BackendConsumer*) (/opt/llvm-project@HEAD/lib/libclang-cpp.dylib+0x172d478)
#30 0x0000000107883b08 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::__1::unique_ptr<llvm::raw_pwrite_stream, std::__1::default_delete<llvm::raw_pwrite_stream>>, clang::BackendConsumer*) (/opt/llvm-project@HEAD/lib/libclang-cpp.dylib+0x1725b08)
#31 0x0000000107d037d3 clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/opt/llvm-project@HEAD/lib/libclang-cpp.dylib+0x1ba57d3)
#32 0x000000010635df1d clang::ParseAST(clang::Sema&, bool, bool) (/opt/llvm-project@HEAD/lib/libclang-cpp.dylib+0x1fff1d)
#33 0x000000010877f3d7 clang::FrontendAction::Execute() (/opt/llvm-project@HEAD/lib/libclang-cpp.dylib+0x26213d7)
#34 0x00000001086e0500 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/llvm-project@HEAD/lib/libclang-cpp.dylib+0x2582500)
#35 0x00000001087f60e9 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/llvm-project@HEAD/lib/libclang-cpp.dylib+0x26980e9)
#36 0x000000010128d4f9 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/opt/llvm-project@HEAD/bin/clang-20+0x1000084f9)
#37 0x0000000101289f88 ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) (/opt/llvm-project@HEAD/bin/clang-20+0x100004f88)
#38 0x00000001082b552e void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<std::__1::optional<llvm::StringRef>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>*, bool*) const::$_0>(long) (/opt/llvm-project@HEAD/lib/libclang-cpp.dylib+0x215752e)
#39 0x0000000112df288c llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/opt/llvm-project@HEAD/lib/libLLVM.dylib+0x31be88c)
#40 0x00000001082b5431 clang::driver::CC1Command::Execute(llvm::ArrayRef<std::__1::optional<llvm::StringRef>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>*, bool*) const (/opt/llvm-project@HEAD/lib/libclang-cpp.dylib+0x2157431)
#41 0x0000000108262131 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/opt/llvm-project@HEAD/lib/libclang-cpp.dylib+0x2104131)
#42 0x00000001082623bf clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::__1::pair<int, clang::driver::Command const*>>&, bool) const (/opt/llvm-project@HEAD/lib/libclang-cpp.dylib+0x21043bf)
#43 0x00000001082b00c0 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::__1::pair<int, clang::driver::Command const*>>&) (/opt/llvm-project@HEAD/lib/libclang-cpp.dylib+0x21520c0)
#44 0x00000001012892b3 clang_main(int, char**, llvm::ToolContext const&) (/opt/llvm-project@HEAD/bin/clang-20+0x1000042b3)
#45 0x00000001012984cb main (/opt/llvm-project@HEAD/bin/clang-20+0x1000134cb)
#46 0x00007ff81a82a345
clang: error: clang frontend command failed with exit code 139 (use -v to see invocation)
clang version 20.0.0git (https://github.com/llvm/llvm-project.git c25c6c32494c8d1038438b6208d42ba40f25270e)
Target: x86_64-apple-darwin23.6.0
Thread model: posix
InstalledDir: /opt/llvm-project@HEAD/bin
clang: note: diagnostic msg:
********************
```

Find attached the preprocessed source code at [gc-add69e.c.gz](https://github.com/user-attachments/files/17813033/gc-add69e.c.gz).

Reproducer: https://godbolt.org/z/Ts478aen6
```
; bin/opt -passes=instcombine test.ll -S
@GC_arrays = external global { i8, i8, i64 }

define ptr @GC_push_finalizer_structures() {
entry:
  %aligned_result.i = call ptr @llvm.ptrmask.p0.i64(ptr getelementptr inbounds (i8, ptr @GC_arrays, i64 1), i64 -8)
  ret ptr %aligned_result.i
}
```
```
opt: /root/llvm-project/llvm/include/llvm/Support/Casting.h:578: decltype(auto) llvm::cast(From*) [with To = llvm::GetElementPtrInst; From = llvm::Value]: Assertion `isa<To>(Val) && "cast<Ty>() argument of incompatible type!"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/opt -o /app/output.s -S -passes=instcombine <source>
1.	Running pass "function(instcombine<max-iterations=1;verify-fixpoint>)" on module "<source>"
2.	Running pass "instcombine<max-iterations=1;verify-fixpoint>" on function "GC_push_finalizer_structures"
 #0 0x0000000005194b38 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x5194b38)
 #1 0x000000000519252c SignalHandler(int) Signals.cpp:0:0
 #2 0x000074b7d8442520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x000074b7d84969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x000074b7d8442476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x000074b7d84287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x000074b7d842871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
 #7 0x000074b7d8439e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
 #8 0x00000000040d9310 decltype(auto) llvm::cast<llvm::GetElementPtrInst, llvm::Value>(llvm::Value*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x40d9310)
 #9 0x00000000040e2f9e llvm::InstCombinerImpl::SimplifyDemandedUseBits(llvm::Instruction*, llvm::APInt const&, llvm::KnownBits&, unsigned int, llvm::SimplifyQuery const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x40e2f9e)
#10 0x00000000040e6082 llvm::InstCombinerImpl::SimplifyDemandedInstructionBits(llvm::Instruction&, llvm::KnownBits&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x40e6082)
#11 0x00000000040355a6 llvm::InstCombinerImpl::visitCallInst(llvm::CallInst&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x40355a6)
#12 0x0000000003fe2311 llvm::InstCombinerImpl::run() (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x3fe2311)
#13 0x0000000003fe3cc6 combineInstructionsOverFunction(llvm::Function&, llvm::InstructionWorklist&, llvm::AAResults*, llvm::AssumptionCache&, llvm::TargetLibraryInfo&, llvm::TargetTransformInfo&, llvm::DominatorTree&, llvm::OptimizationRemarkEmitter&, llvm::BlockFrequencyInfo*, llvm::BranchProbabilityInfo*, llvm::ProfileSummaryInfo*, llvm::InstCombineOptions const&) (.isra.0) InstructionCombining.cpp:0:0
#14 0x0000000003fe504e llvm::InstCombinePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x3fe504e)
#15 0x0000000002c5c24e llvm::detail::PassModel<llvm::Function, llvm::InstCombinePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x2c5c24e)
#16 0x0000000004f949e8 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4f949e8)
#17 0x0000000000e4027e 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+0xe4027e)
#18 0x0000000004f9340e llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4f9340e)
#19 0x0000000000e3f92e 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+0xe3f92e)
#20 0x0000000004f92e40 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4f92e40)
#21 0x0000000000909fda 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+0x909fda)
#22 0x00000000008fc70a optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8fc70a)
#23 0x000074b7d8429d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#24 0x000074b7d8429e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#25 0x00000000008f3e9e _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8f3e9e)
Program terminated with signal: SIGSEGV
Compiler returned: 139
```


commit ff07df6620c32571c7e13ff96ec7976c63ed0ab8
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Fri Nov 8 16:20:04 2024 +0800

    [InstCombine] Drop nsw in negation of select (#112893)

    Closes https://github.com/llvm/llvm-project/issues/112666 and
    https://github.com/llvm/llvm-project/issues/114181.

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp b/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
index 9bd848552615..2210336d92bf 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
@@ -333,6 +333,17 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
       NewSelect->swapValues();
       // Don't swap prof metadata, we didn't change the branch behavior.
       NewSelect->setName(I->getName() + ".neg");
+      // Poison-generating flags should be dropped
+      Value *TV = NewSelect->getTrueValue();
+      Value *FV = NewSelect->getFalseValue();
+      if (match(TV, m_Neg(m_Specific(FV))))
+        cast<Instruction>(TV)->dropPoisonGeneratingFlags();
+      else if (match(FV, m_Neg(m_Specific(TV))))
+        cast<Instruction>(FV)->dropPoisonGeneratingFlags();
+      else {
+        cast<Instruction>(TV)->dropPoisonGeneratingFlags();
+        cast<Instruction>(FV)->dropPoisonGeneratingFlags();
+      }
       Builder.Insert(NewSelect);
       return NewSelect;
     }

define i8 @negate_select_of_op_vs_negated_op_nsw_commuted(i8 %x, i8 %y, i1 %c) {
  %t0 = sub nsw i8 0, %x
  %t1 = select i1 %c, i8 %x, i8 %t0
  %t2 = sub i8 %y, %t1
  ret i8 %t2
}

define i8 @negate_select_of_op_vs_negated_op_nsw(i8 %x, i8 %y, i1 %c) {
  %t0 = sub nsw i8 0, %x
  %t1 = select i1 %c, i8 %t0, i8 %x
  %t2 = sub i8 %y, %t1
  ret i8 %t2
}

define i8 @dont_negate_ordinary_select(i8 %x, i8 %y, i8 %z, i1 %c) {
  %t0 = select i1 %c, i8 %x, i8 %y
  %t1 = sub i8 %z, %t0
  ret i8 %t1
}

define i8 @negate_select_of_op_vs_negated_op_nsw_xyyx(i8 %x, i8 %y, i8 %z, i1 %c) {
  %sub1 = sub nsw i8 %x, %y
  %sub2 = sub nsw i8 %y, %x
  %t1 = select i1 %c, i8 %sub1, i8 %sub2
  %t2 = sub i8 %z, %t1
  ret i8 %t2
}

declare void @use8(i8)

define i8 @negate_select_of_op_vs_negated_op(i8 %x, i8 %y, i1 %c) {
  %t0 = sub i8 0, %x
  call void @use8(i8 %t0)
  %t1 = select i1 %c, i8 %t0, i8 %x, !prof !0
  %t2 = sub i8 %y, %t1
  ret i8 %t2
}

!0 = !{!"branch_weights", i32 40, i32 1}

[InstCombine] `nsw` flag should be dropped in Negator

Reproducer: https://alive2.llvm.org/ce/z/ZFF_QK
```
define i8 @src(i8 %x, i8 %y, i1 %c) {
  %t0 = sub nsw i8 0, %x
  %t1 = select i1 %c, i8 %t0, i8 %x
  %t2 = sub i8 %y, %t1
  ret i8 %t2
}

define i8 @tgt(i8 %x, i8 %y, i1 %c) {
  %t0 = sub nsw i8 0, %x
  %1 = select i1 %c, i8 %x, i8 %t0
  %t2 = add i8 %1, %y
  ret i8 %t2
}
```
```
Transformation doesn't verify!

ERROR: Target is more poisonous than source

Example:
i8 %x = #x80 (128, -128)
i8 %y = #x00 (0)
i1 %c = #x0 (0)

Source:
i8 %t0 = poison
i8 %t1 = #x80 (128, -128)
i8 %t2 = #x80 (128, -128)

Target:
i8 %t0 = poison
i8 %#1 = poison
i8 %t2 = poison
Source value: #x80 (128, -128)
Target value: poison
```

Is this an issue in 19.x or just main?

Confirmed this issue exists in 19.x


commit e1d22512906e69846c8f6a2d29b30832b7c12b46
Author: Alexey Bataev <a.bataev@outlook.com>
Date:   Mon Aug 26 11:30:13 2024 -0700

    [SLP]Fix minbitwidth analysis for gather nodes with icmp users.

    If the node is not in MinBWs container and the user node is icmp node,
    the compiler should not check the type size of the user instruction, it
    is always 1 and is not good for actual bitwidth analysis.

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

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index def73e8d0c0d..ed47ed661ab9 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -15975,6 +15975,10 @@ void BoUpSLP::computeMinimumValueSizes() {
                     auto It = MinBWs.find(TE);
                     if (It != MinBWs.end() && It->second.first > UserTESz)
                       return true;
+                    // The size of icmp is always 1 and should not be
+                    // considered.
+                    if (TE->getOpcode() == Instruction::ICmp)
+                      return true;
                     return DL->getTypeSizeInBits(U->getType()) > UserTESz;
                   }));
         })) {

define i1 @test(i32 %g, i16 %d) {
entry:
  %0 = and i16 %d, 1
  %xor.i.i = xor i32 %g, 1
  %conv1.i.i = trunc i32 %xor.i.i to i8
  %notsub.i = add i8 %conv1.i.i, -1
  %cmp.i.i = icmp sgt i8 %notsub.i, -3
  %conv3.i.i = zext i1 %cmp.i.i to i32
  %cmp4.i.i = icmp sgt i32 %xor.i.i, %conv3.i.i
  %conv1.1.i.i = trunc i32 %g to i8
  %notsub25.i = add i8 %conv1.1.i.i, -1
  %cmp.1.i.i = icmp sgt i8 %notsub25.i, -3
  %conv3.1.i.i = zext i1 %cmp.1.i.i to i32
  %cmp4.1.i.i = icmp sgt i32 %g, %conv3.1.i.i
  %notsub26.i = add i8 %conv1.1.i.i, -9
  %cmp.i17.i = icmp sgt i8 %notsub26.i, -3
  %conv3.i18.i = zext i1 %cmp.i17.i to i32
  %cmp4.i19.i = icmp sgt i32 %g, %conv3.i18.i
  %notsub27.i = add i8 %conv1.i.i, -9
  %cmp.1.i22.i = icmp sgt i8 %notsub27.i, -3
  %conv3.1.i23.i = zext i1 %cmp.1.i22.i to i32
  %cmp4.1.i24.i = icmp sgt i32 %xor.i.i, %conv3.1.i23.i
  %1 = and i1 %cmp4.i19.i, %cmp4.1.i24.i
  %2 = and i1 %cmp4.i.i, %1
  %3 = and i1 %cmp4.1.i.i, %2
  ret i1 %3
}

[SLPVectorizer] Miscompile at O3

Reproducer: https://gist.github.com/dtcxzyw/117dc735db97658ea852d30fd896242a
```console
> bin/clang -O0 test.c -w -I/usr/include/csmith && ./a.out
checksum = BDCB7A78
> bin/clang -O3 test.c -w -mllvm -inline-threshold=100000 -I/usr/include/csmith && ./a.out
checksum = 9198FC41
```

llvm version: 1193f7d6487d2d94009f8d8d27da3907136482b9

Reproducer: https://alive2.llvm.org/ce/z/GCXoe9
```
; bin/opt -passes=slp-vectorizer test.ll -S

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

define i1 @main(i32 %g.promoted.i.i, i16 %d.promoted.i.i) {
entry:
  %0 = and i16 %d.promoted.i.i, 1
  %xor.i.i = xor i32 %g.promoted.i.i, 1
  %conv1.i.i = trunc i32 %xor.i.i to i8
  %notsub.i = add i8 %conv1.i.i, -1
  %cmp.i.i = icmp sgt i8 %notsub.i, -3
  %conv3.i.i = zext i1 %cmp.i.i to i32
  %cmp4.i.i = icmp sgt i32 %xor.i.i, %conv3.i.i
  %conv1.1.i.i = trunc i32 %g.promoted.i.i to i8
  %notsub25.i = add i8 %conv1.1.i.i, -1
  %cmp.1.i.i = icmp sgt i8 %notsub25.i, -3
  %conv3.1.i.i = zext i1 %cmp.1.i.i to i32
  %cmp4.1.i.i = icmp sgt i32 %g.promoted.i.i, %conv3.1.i.i
  %notsub26.i = add i8 %conv1.1.i.i, -9
  %cmp.i17.i = icmp sgt i8 %notsub26.i, -3
  %conv3.i18.i = zext i1 %cmp.i17.i to i32
  %cmp4.i19.i = icmp sgt i32 %g.promoted.i.i, %conv3.i18.i
  %notsub27.i = add i8 %conv1.i.i, -9
  %cmp.1.i22.i = icmp sgt i8 %notsub27.i, -3
  %conv3.1.i23.i = zext i1 %cmp.1.i22.i to i32
  %cmp4.1.i24.i = icmp sgt i32 %xor.i.i, %conv3.1.i23.i
  %1 = and i1 %cmp4.i19.i, %cmp4.1.i24.i
  %2 = and i1 %cmp4.i.i, %1
  %3 = and i1 %cmp4.1.i.i, %2
  ret i1 %3
}
```
Output:
```
define i1 @main(i32 %g.promoted.i.i, i16 %d.promoted.i.i) {
entry:
  %0 = and i16 %d.promoted.i.i, 1
  %xor.i.i = xor i32 %g.promoted.i.i, 1
  %1 = trunc i32 %g.promoted.i.i to i8
  %2 = insertelement <2 x i8> poison, i8 %1, i32 0
  %3 = trunc i32 %xor.i.i to i8
  %4 = insertelement <2 x i8> %2, i8 %3, i32 1
  %5 = shufflevector <2 x i8> %4, <2 x i8> poison, <4 x i32> <i32 0, i32 1, i32 0, i32 1>
  %6 = add <4 x i8> %5, <i8 -9, i8 -9, i8 -1, i8 -1>
  %7 = icmp sgt <4 x i8> %6, <i8 -3, i8 -3, i8 -3, i8 -3>
  %8 = zext <4 x i1> %7 to <4 x i8>
  %9 = sext <2 x i8> %4 to <2 x i32>
  %10 = shufflevector <2 x i32> %9, <2 x i32> poison, <4 x i32> <i32 0, i32 1, i32 0, i32 1>
  %11 = zext <4 x i8> %8 to <4 x i32>
  %12 = icmp sgt <4 x i32> %10, %11
  %13 = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> %12)
  ret i1 %13
}
```

cc @alexey-bataev


ComputeNumSignBitsImpl computeKnownBitsFromOperator computeKnownFPClass isKnownNonZeroFromOperator isKnownToBeAPowerOfTwo isNonEqualPHIs

commit a87fbeb3a77a53ded341277c5b326f7696d47594
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Wed Jul 24 20:06:36 2024 +0800

    [ValueTracking] Don't use CondContext in dataflow analysis of phi nodes (#100316)

    See the following case:
    ```
    define i16 @pr100298() {
    entry:
      br label %for.inc

    for.inc:
      %indvar = phi i32 [ -15, %entry ], [ %mask, %for.inc ]
      %add = add nsw i32 %indvar, 9
      %mask = and i32 %add, 65535
      %cmp1 = icmp ugt i32 %mask, 5
      br i1 %cmp1, label %for.inc, label %for.end

    for.end:
      %conv = trunc i32 %add to i16
      %cmp2 = icmp ugt i32 %mask, 3
      %shl = shl nuw i16 %conv, 14
      %res = select i1 %cmp2, i16 %conv, i16 %shl
      ret i16 %res
    }
    ```

    When computing knownbits of `%shl` with `%cmp2=false`, we cannot use
    this condition in the analysis of `%mask (%for.inc -> %for.inc)`.

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

    (cherry picked from commit 59eae919c938f890e9b9b4be8a3fa3cb1b11ed89)

diff --git a/llvm/include/llvm/Analysis/SimplifyQuery.h b/llvm/include/llvm/Analysis/SimplifyQuery.h
index a560744f0122..e8f43c8c2e91 100644
--- a/llvm/include/llvm/Analysis/SimplifyQuery.h
+++ b/llvm/include/llvm/Analysis/SimplifyQuery.h
@@ -130,6 +130,12 @@ struct SimplifyQuery {
     Copy.CC = &CC;
     return Copy;
   }
+
+  SimplifyQuery getWithoutCondContext() const {
+    SimplifyQuery Copy(*this);
+    Copy.CC = nullptr;
+    return Copy;
+  }
 };

 } // end namespace llvm
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 40fe1ffe13f1..4b77c0046cc7 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -1435,7 +1435,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
         // inferred hold at original context instruction.  TODO: It may be
         // correct to use the original context.  IF warranted, explore and
         // add sufficient tests to cover.
-        SimplifyQuery RecQ = Q;
+        SimplifyQuery RecQ = Q.getWithoutCondContext();
         RecQ.CxtI = P;
         computeKnownBits(R, DemandedElts, Known2, Depth + 1, RecQ);
         switch (Opcode) {
@@ -1468,7 +1468,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
         // phi. This is important because that is where the value is actually
         // "evaluated" even though it is used later somewhere else. (see also
         // D69571).
-        SimplifyQuery RecQ = Q;
+        SimplifyQuery RecQ = Q.getWithoutCondContext();

         unsigned OpNum = P->getOperand(0) == R ? 0 : 1;
         Instruction *RInst = P->getIncomingBlock(OpNum)->getTerminator();
@@ -1546,7 +1546,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
         // phi. This is important because that is where the value is actually
         // "evaluated" even though it is used later somewhere else. (see also
         // D69571).
-        SimplifyQuery RecQ = Q;
+        SimplifyQuery RecQ = Q.getWithoutCondContext();
         RecQ.CxtI = P->getIncomingBlock(u)->getTerminator();

         Known2 = KnownBits(BitWidth);
@@ -2329,7 +2329,7 @@ bool isKnownToBeAPowerOfTwo(const Value *V, bool OrZero, unsigned Depth,
     // it is an induction variable where in each step its value is a power of
     // two.
     auto *PN = cast<PHINode>(I);
-    SimplifyQuery RecQ = Q;
+    SimplifyQuery RecQ = Q.getWithoutCondContext();

     // Check if it is an induction variable and always power of two.
     if (isPowerOfTwoRecurrence(PN, OrZero, Depth, RecQ))
@@ -2943,7 +2943,7 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
       return true;

     // Check if all incoming values are non-zero using recursion.
-    SimplifyQuery RecQ = Q;
+    SimplifyQuery RecQ = Q.getWithoutCondContext();
     unsigned NewDepth = std::max(Depth, MaxAnalysisRecursionDepth - 1);
     return llvm::all_of(PN->operands(), [&](const Use &U) {
       if (U.get() == PN)
@@ -3509,7 +3509,7 @@ static bool isNonEqualPHIs(const PHINode *PN1, const PHINode *PN2,
     if (UsedFullRecursion)
       return false;

-    SimplifyQuery RecQ = Q;
+    SimplifyQuery RecQ = Q.getWithoutCondContext();
     RecQ.CxtI = IncomBB->getTerminator();
     if (!isKnownNonEqual(IV1, IV2, DemandedElts, Depth + 1, RecQ))
       return false;
@@ -4001,7 +4001,7 @@ static unsigned ComputeNumSignBitsImpl(const Value *V,

       // Take the minimum of all incoming values.  This can't infinitely loop
       // because of our depth threshold.
-      SimplifyQuery RecQ = Q;
+      SimplifyQuery RecQ = Q.getWithoutCondContext();
       Tmp = TyBits;
       for (unsigned i = 0, e = NumIncomingValues; i != e; ++i) {
         if (Tmp == 1) return Tmp;
@@ -5909,10 +5909,10 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
         // Recurse, but cap the recursion to two levels, because we don't want
         // to waste time spinning around in loops. We need at least depth 2 to
         // detect known sign bits.
-        computeKnownFPClass(
-            IncValue, DemandedElts, InterestedClasses, KnownSrc,
-            PhiRecursionLimit,
-            Q.getWithInstruction(P->getIncomingBlock(U)->getTerminator()));
+        computeKnownFPClass(IncValue, DemandedElts, InterestedClasses, KnownSrc,
+                            PhiRecursionLimit,
+                            Q.getWithoutCondContext().getWithInstruction(
+                                P->getIncomingBlock(U)->getTerminator()));

         if (First) {
           Known = KnownSrc;

define i16 @pr100298() {
entry:
  br label %for.inc

for.inc:                                          ; preds = %for.inc, %entry
  %indvar = phi i32 [ -15, %entry ], [ %mask, %for.inc ]
  %add = add nsw i32 %indvar, 9
  %mask = and i32 %add, 65535
  %cmp1 = icmp ugt i32 %mask, 5
  br i1 %cmp1, label %for.inc, label %for.end

for.end:                                          ; preds = %for.inc
  %conv = trunc i32 %add to i16
  %cmp2 = icmp ugt i32 %mask, 3
  %shl = shl nuw i16 %conv, 14
  %res = select i1 %cmp2, i16 %conv, i16 %shl
  ret i16 %res
}

Miscompilation at O3

```
#include "csmith.h"
uint32_t a;
int16_t c;
void d() {
  for (a = -15; a >= 6; a = safe_add_func_uint16_t_u_u(a, 9))
    ;
  c = safe_lshift_func_int16_t_s_u(safe_lshift_func_uint16_t_u_s(a,14), 0);
}
int main() {
  d();
  printf("%d\n", c);
  return 0;
}
```

```
dtcxzyw@dtcxzyw:~/WorkSpace/Projects/compilers/LLVM/llvm-build$ gcc -O0 test.c -fsanitize=undefined -I/usr/include/csmith -w
dtcxzyw@dtcxzyw:~/WorkSpace/Projects/compilers/LLVM/llvm-build$ ./a.out
-16384
dtcxzyw@dtcxzyw:~/WorkSpace/Projects/compilers/LLVM/llvm-build$ bin/clang -O3 test.c -I/usr/include/csmith -w
dtcxzyw@dtcxzyw:~/WorkSpace/Projects/compilers/LLVM/llvm-build$ ./a.out
0
```

llvm version: 2d6ff0c533aa1b0fe6d91764846f636c4a4e911c

Reduced testcase: https://alive2.llvm.org/ce/z/9fExrA
```
; bin/opt -passes=instcombine test.ll -S
define i16 @src() {
entry:
  br label %for.inc

for.inc:
  %storemerge6 = phi i32 [ -15, %entry ], [ %conv1, %for.inc ]
  %add.i = add nsw i32 %storemerge6, 9
  %conv1 = and i32 %add.i, 65535
  %cmp = icmp ugt i32 %conv1, 5
  br i1 %cmp, label %for.inc, label %for.end

for.end:
  %conv2 = trunc nuw nsw i32 %conv1 to i16
  %cmp3.i = icmp ugt i32 %conv1, 3
  %0 = shl nuw i16 %conv2, 14
  %cond.in.i = select i1 %cmp3.i, i16 %conv2, i16 %0
  ret i16 %cond.in.i
}
```