Bug type: crash
Component: SCCPSolver
Bug location: llvm/lib/Transforms/Utils/SCCPSolver.cpp: SCCPInstVisitor::visitCastInst
Issue title: [SCCP] Assertion `getConstant() == V && "Marking constant with different value"' failed.
Labels: crash-on-valid
llvm:transforms
Reported by: XChy

Reproducer: https://godbolt.org/z/6EPEPEvnc
Testcase:
```llvm
define <32 x i8> @backsmith_pure_1(i1 %cond) {
entry:
  br label %for.cond2

for.cond2:                                        ; preds = %for.cond2, %entry
  %BS_VAR_1.0 = phi <4 x i64> [ <i64 poison, i64 poison, i64 poison, i64 0>, %entry ], [ zeroinitializer, %for.cond2 ]
  %0 = phi <4 x i64> [ zeroinitializer, %entry ], [ splat (i64 1), %for.cond2 ]
  br i1 %cond, label %for.cond2, label %if.then

if.then:                                          ; preds = %for.cond2
  %sub = sub <4 x i64> <i64 poison, i64 poison, i64 poison, i64 0>, %BS_VAR_1.0
  %and = and <4 x i64> %0, %sub
  %1 = bitcast <4 x i64> %and to <32 x i8>
  ret <32 x i8> %1
}
```

Dump:
```
opt: /root/llvm-project/llvm/include/llvm/Analysis/ValueLattice.h:319: bool llvm::ValueLatticeElement::markConstant(llvm::Constant*, bool): Assertion `getConstant() == V && "Marking constant with different value"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and instructions to reproduce the bug.
Stack dump:
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/opt -o /app/output.s -S --passes=sccp <source>
1.	Running pass "function(sccp)" on module "<source>"
2.	Running pass "sccp" on function "backsmith_pure_1"
 #0 0x00000000059be998 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x59be998)
 #1 0x00000000059bb844 SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
 #2 0x0000759af6642520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x0000759af66969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x0000759af6642476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x0000759af66287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x0000759af662871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
 #7 0x0000759af6639e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
 #8 0x0000000004c46f35 llvm::ValueLatticeElement::markConstant(llvm::Constant*, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4c46f35)
 #9 0x0000000004c57414 llvm::SCCPInstVisitor::markConstant(llvm::Value*, llvm::Constant*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4c57414)
#10 0x0000000004c58f4e llvm::SCCPInstVisitor::visitCastInst(llvm::CastInst&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4c58f4e)
#11 0x0000000004c592e3 llvm::SCCPInstVisitor::solve() (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4c592e3)
#12 0x000000000482f15a llvm::SCCPPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x482f15a)
#13 0x0000000002ff434e llvm::detail::PassModel<llvm::Function, llvm::SCCPPass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x2ff434e)
#14 0x000000000579be41 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x579be41)
#15 0x0000000000f0774e 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+0xf0774e)
#16 0x000000000579a50a llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x579a50a)
#17 0x0000000000973a7e 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+0x973a7e)
#18 0x0000000005799ec1 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x5799ec1)
#19 0x000000000097ddaa 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, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x97ddaa)
#20 0x0000000000971c28 optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x971c28)
#21 0x0000759af6629d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#22 0x0000759af6629e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#23 0x00000000009686c5 _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x9686c5)
Program terminated with signal: SIGSEGV
Compiler returned: 139
```

Comments: author: milos1397
body: can you assign this one to me?


Fix patch:
commit 991455e69e93c0ce88e927eddd28a9ab34d1f8b2
Author: Miloš Poletanović <poletanovicmilos97@gmail.com>
Date:   Thu Dec 25 13:41:50 2025 +0100

    [SCCP] Use mergeInValue instead of markConstant when folding CastInst (#173190)
    
    Fixes #173180
    
    The crash occurs when a vector constant refines its value during
    iterative analysis.
    In `SCCPInstVisitor::visitCastInst`, the logic for folding constants
    through a `CastInst` uses `markConstant`. This function is strictly
    designed for initial assignments and contains an assertion that prevents
    a lattice element from being updated with a different constant pointer.
    
    During the analysis of loops or complex data flows, a vector constant
    may "refine." For example:
    
    First Pass: SCCP identifies a value as `<4 x i64> {poison, poison,
    poison, 0}`.
    
    Second Pass: The value refines to `<4 x i64> zeroinitializer`.
    
    Because these are distinct `Constant*` objects, `markConstant` triggers
    a `"Marking constant with different value"` assertion failure.
    
    The call to `markConstant` is replaced with `mergeInValue`. Unlike the
    former, `mergeInValue` is lattice-aware, it allows for valid refinement
    (moving from a less-defined to a more-defined state) and gracefully
    handles transitions to Overdefined if a true conflict occurs. This
    brings BitCast handling in line with how Trunc and Ext instructions are
    already safely handled in the same pass.
    
    Co-authored-by: Milos Poletanovic <mpoletanovic@syrmia.com>

diff --git a/llvm/lib/Transforms/Utils/SCCPSolver.cpp b/llvm/lib/Transforms/Utils/SCCPSolver.cpp
index 021bf0618754..90ee55b87439 100644
--- a/llvm/lib/Transforms/Utils/SCCPSolver.cpp
+++ b/llvm/lib/Transforms/Utils/SCCPSolver.cpp
@@ -1498,8 +1498,11 @@ void SCCPInstVisitor::visitCastInst(CastInst &I) {
   if (Constant *OpC = getConstant(OpSt, I.getOperand(0)->getType())) {
     // Fold the constant as we build.
     if (Constant *C =
-            ConstantFoldCastOperand(I.getOpcode(), OpC, I.getType(), DL))
-      return (void)markConstant(&I, C);
+            ConstantFoldCastOperand(I.getOpcode(), OpC, I.getType(), DL)) {
+      auto &LV = ValueState[&I];
+      mergeInValue(LV, &I, ValueLatticeElement::get(C));
+      return;
+    }
   }
 
   // Ignore bitcasts, as they may change the number of vector elements.


Regression tests:
file: llvm/test/Transforms/SCCP/bitcast-vector-refinement.l.ll
commands: opt -passes=sccp -S < %s
tests: test_name: <module>
test_body: 
define <32 x i8> @test(i1 %cond) {
;
entry:
  br label %for.cond2

for.cond2:                                        ; preds = %for.cond2, %entry
  %BS_VAR_1.0 = phi <4 x i64> [ <i64 poison, i64 poison, i64 poison, i64 0>, %entry ], [ zeroinitializer, %for.cond2 ]
  %0 = phi <4 x i64> [ zeroinitializer, %entry ], [ splat (i64 1), %for.cond2 ]
  br i1 %cond, label %for.cond2, label %if.then

if.then:                                          ; preds = %for.cond2
  %sub = sub <4 x i64> <i64 poison, i64 poison, i64 poison, i64 0>, %BS_VAR_1.0
  %and = and <4 x i64> %0, %sub
  %1 = bitcast <4 x i64> %and to <32 x i8>
  ret <32 x i8> %1
}