[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