[llvm] [ConstantFolding] Support bitcasting vectors to smaller element sizes with non-integer ratios. (PR #179640)
Kacper Doga via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 11 01:21:57 PST 2026
================
@@ -262,36 +261,65 @@ Constant *FoldBitCast(Constant *C, Type *DestTy, const DataLayout &DL) {
}
// Handle: bitcast (<2 x i64> <i64 0, i64 1> to <4 x i32>)
+ // bitcast (<3 x i64> <i64 0, i64 1, i64 2> to <8 x i24>)
unsigned Ratio = NumDstElt/NumSrcElt;
unsigned DstBitSize = DL.getTypeSizeInBits(DstEltTy);
-
- // Loop over each source value, expanding into multiple results.
- for (unsigned i = 0; i != NumSrcElt; ++i) {
- auto *Element = C->getAggregateElement(i);
-
+ APInt Rest(SrcBitSize, 0);
+ unsigned RestSize = 0;
+ for (unsigned i = 0; i != NumSrcElt || Result.size() != NumDstElt;) {
+ unsigned UnusedBits = SrcBitSize - RestSize;
+ if (RestSize == DstBitSize) {
+ // Shift the rest into the right place.
+ Rest.lshrInPlace(isLittleEndian ? UnusedBits : 0);
+ Result.push_back(ConstantInt::get(DstEltTy, Rest.trunc(DstBitSize)));
+ RestSize = 0;
+ Rest.clearAllBits();
+ continue;
+ }
+ auto *Element = C->getAggregateElement(i++);
if (!Element) // Reject constantexpr elements.
return ConstantExpr::getBitCast(C, DestTy);
+ APInt NextVecElem;
if (isa<UndefValue>(Element)) {
// Correctly Propagate undef values.
- Result.append(Ratio, UndefValue::get(DstEltTy));
- continue;
+ if (SrcBitSize % DstBitSize == 0) {
+ Result.append(Ratio, UndefValue::get(DstEltTy));
+ continue;
+ }
+ // Replace Undef with zeros to prevent partial corruption.
+ NextVecElem = APInt::getZero(SrcBitSize);
+ } else {
----------------
varev-dev wrote:
I considered two options how to handle undef value in case where ratio is non-integer:
1. Replace undef with zeros e.g.:
```llvm
; CHECK-NEXT: ret <4 x i24> <i24 0, i24 256, i24 0, i24 0>
%c = bitcast <3 x i32> <i32 undef, i32 1, i32 undef> to <4 x i24>
ret <4 x i24> %c
```
2. Replace only the part merged with non-undef value e.g.:
```llvm
; CHECK-NEXT: ret <4 x i24> <i24 undef, i24 256, i24 0, i24 undef>
%c = bitcast <3 x i32> <i32 undef, i32 1, i32 undef> to <4 x i24>
ret <4 x i24> %c
```
I decided to go with option 1, that way it significantly simplifies the bit-stream logic.
https://github.com/llvm/llvm-project/pull/179640
More information about the llvm-commits
mailing list