llvm-project/llvm/test/Transforms/SCCP/bitcast-vector-refinement.l.ll
Miloš Poletanović 991455e69e
[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>
2025-12-25 20:41:50 +08:00

30 lines
1.3 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt -passes=sccp -S < %s | FileCheck %s
define <32 x i8> @test(i1 %cond) {
; CHECK-LABEL: define <32 x i8> @test(
; CHECK-SAME: i1 [[COND:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*]]:
; CHECK-NEXT: br label %[[FOR_COND2:.*]]
; CHECK: [[FOR_COND2]]:
; CHECK-NEXT: [[TMP0:%.*]] = phi <4 x i64> [ zeroinitializer, %[[ENTRY]] ], [ splat (i64 1), %[[FOR_COND2]] ]
; CHECK-NEXT: br i1 [[COND]], label %[[FOR_COND2]], label %[[IF_THEN:.*]]
; CHECK: [[IF_THEN]]:
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i64> zeroinitializer to <32 x i8>
; CHECK-NEXT: ret <32 x i8> [[TMP1]]
;
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
}