[llvm] [ConstantFolding] Fix dropped bits in non-integer-ratio bitcast with undef lane (PR #202282)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 8 01:05:44 PDT 2026
https://github.com/lijinpei-amd created https://github.com/llvm/llvm-project/pull/202282
When constant-folding a vector bitcast(e.g. <4 x i24> -> <3 x i32>), an undef source element inserted a DstBitSize-wide zero placeholder into the bit buffer. This could clobber defined source element, producing a wrong result on big-endian targets.
Fix by inserting SrcBitSize-wide zero instead.
Alive2 proof:
before (unsound): https://alive2.llvm.org/ce/z/R_ZQ75
after (verified): https://alive2.llvm.org/ce/z/VuV3mz
>From de3c6528567f7b1de94c04bb55a6e57c95da27f8 Mon Sep 17 00:00:00 2001
From: Li Jinpei <jinpli at amd.com>
Date: Sat, 6 Jun 2026 21:45:47 +0800
Subject: [PATCH] [ConstantFolding] Fix dropped bits in non-integer-ratio
bitcast with undef lane
When constant-folding a vector bitcast(e.g. <4 x i24> -> <3 x i32>), an undef source element inserted a
DstBitSize-wide zero placeholder into the bit buffer. This could clobber defined source element, producing a wrong result on
big-endian targets.
Fix by inserting SrcBitSize-wide zero instead.
Alive2 proof:
before (unsound): https://alive2.llvm.org/ce/z/R_ZQ75
after (verified): https://alive2.llvm.org/ce/z/VuV3mz
---
llvm/lib/Analysis/ConstantFolding.cpp | 6 +++++-
llvm/test/Transforms/InstSimplify/bitcast-vector-fold.ll | 2 +-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 959b46f8eff46..4bb8bd8d7b583 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -359,7 +359,11 @@ Constant *FoldBitCast(Constant *C, Type *DestTy, const DataLayout &DL) {
UndefMask.setBits(BitPosition, BitPosition + SrcBitSize);
if (isa<PoisonValue>(Element))
PoisonMask.setBits(BitPosition, BitPosition + SrcBitSize);
- SrcValue = APInt::getZero(DstBitSize);
+ // The placeholder value must be exactly SrcBitSize wide. Using a wider
+ // value here would clear DstBitSize bits via insertBits and clobber
+ // bits belonging to a previously loaded (defined) source element,
+ // producing an incorrect result for non-integer element ratios.
+ SrcValue = APInt::getZero(SrcBitSize);
} else {
auto *Src = dyn_cast<ConstantInt>(Element);
if (!Src)
diff --git a/llvm/test/Transforms/InstSimplify/bitcast-vector-fold.ll b/llvm/test/Transforms/InstSimplify/bitcast-vector-fold.ll
index 88f34cabc6188..14789847911a5 100644
--- a/llvm/test/Transforms/InstSimplify/bitcast-vector-fold.ll
+++ b/llvm/test/Transforms/InstSimplify/bitcast-vector-fold.ll
@@ -412,7 +412,7 @@ define <3 x i32> @bitcast_constexpr_3i32_4i24_n1255uu() {
; LE-NEXT: ret <3 x i32> <i32 -1, i32 0, i32 undef>
;
; BE-LABEL: @bitcast_constexpr_3i32_4i24_n1255uu(
-; BE-NEXT: ret <3 x i32> <i32 -256, i32 0, i32 undef>
+; BE-NEXT: ret <3 x i32> <i32 -256, i32 16711680, i32 undef>
;
%cast = bitcast <4 x i24><i24 -1, i24 255, i24 undef, i24 undef> to <3 x i32>
ret <3 x i32> %cast
More information about the llvm-commits
mailing list