[llvm] [Scalarizer] Ensure valid VectorSplits for each struct element in `visitExtractValueInst` (PR #128538)
Deric Cheung via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 24 10:50:13 PST 2025
================
@@ -1083,6 +1082,18 @@ bool ScalarizerVisitor::visitExtractValueInst(ExtractValueInst &EVI) {
std::optional<VectorSplit> VS = getVectorSplit(VecType);
if (!VS)
return false;
+ for (unsigned I = 1; I < OpTy->getNumContainedTypes(); I++) {
+ std::optional<VectorSplit> CurrVS =
+ getVectorSplit(cast<FixedVectorType>(OpTy->getContainedType(I)));
+ // It is possible for VectorSplit.NumPacked >= NumElems. If that happens a
+ // VectorSplit is not returned and we will bailout of handling this call.
+ // The secondary bailout case is if NumPacked does not match. This can
+ // happen if ScalarizeMinBits is not set to the default. This means with
+ // certain ScalarizeMinBits intrinsics like frexp will only scalarize when
+ // the struct elements have the same bitness.
+ if (!CurrVS || CurrVS->NumPacked != VS->NumPacked)
----------------
Icohedron wrote:
For `*_with_overflow` intrinsics, you are correct that it is only scalarized if `ScalarizeMinBits` is 0.
The reason is because of [this check in the `vectorSplit` function](https://github.com/llvm/llvm-project/blob/823a597d2ad0a76e8d5278a789f37a07b393cd2a/llvm/lib/Transforms/Scalar/Scalarizer.cpp#L586) which will always return an empty VectorSplit when it receives a vector of bools (i1), and the `*_with_overflow` intrinsics always return a vector of bools.
For the frexp case, it is still able to scalarize with a non-zero `ScalarizeMinBits`. For example, the existing `Scalarizer/frexp.ll` test case does not run into an assertion error and is able to scalarize with min-bits=16.
```llvm
define noundef <2 x half> @frexp_v2f8(<2 x half> noundef %h) {
; MIN16-LABEL: @frexp_v2f16(
; MIN16-NEXT: [[H_I0:%.*]] = extractelement <2 x half> [[H:%.*]], i64 0
; MIN16-NEXT: [[R_I0:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[H_I0]])
; MIN16-NEXT: [[H_I1:%.*]] = extractelement <2 x half> [[H]], i64 1
; MIN16-NEXT: [[R_I1:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[H_I1]])
; MIN16-NEXT: [[E0_ELEM0:%.*]] = extractvalue { half, i32 } [[R_I0]], 0
; MIN16-NEXT: [[E0_ELEM01:%.*]] = extractvalue { half, i32 } [[R_I1]], 0
; MIN16-NEXT: [[E0_UPTO0:%.*]] = insertelement <2 x half> poison, half [[E0_ELEM0]], i64 0
; MIN16-NEXT: [[E0:%.*]] = insertelement <2 x half> [[E0_UPTO0]], half [[E0_ELEM01]], i64 1
; MIN16-NEXT: ret <2 x half> [[E0]]
;
; MIN32-LABEL: @frexp_v2f16(
; MIN32-NEXT: [[R:%.*]] = call { <2 x half>, <2 x i32> } @llvm.frexp.v2f16.v2i32(<2 x half> [[H:%.*]])
; MIN32-NEXT: [[E0:%.*]] = extractvalue { <2 x half>, <2 x i32> } [[R]], 0
; MIN32-NEXT: ret <2 x half> [[E0]]
;
%r = call { <2 x half>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x half> %h)
%e0 = extractvalue { <2 x half>, <2 x i32> } %r, 0
ret <2 x half> %e0
}
```
https://github.com/llvm/llvm-project/pull/128538
More information about the llvm-commits
mailing list